blob: b885d2973db9a8e977f27a735163d47265593af0 [file] [log] [blame]
C.J. Collier37141e42020-02-13 13:49:49 -08001# Copyright 2016 Google LLC
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -07002#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14
15import datetime
Hiranya Jayathilaka23c88f72017-12-05 09:29:59 -080016import json
17import os
Bu Sun Kim32d71a52019-12-18 11:30:46 -080018import pickle
19import sys
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070020
21import mock
Thea Flowers118c0482018-05-24 13:34:07 -070022import pytest
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070023
24from google.auth import _helpers
Thea Flowers118c0482018-05-24 13:34:07 -070025from google.auth import exceptions
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070026from google.auth import transport
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070027from google.oauth2 import credentials
28
29
Bu Sun Kim9eec0912019-10-21 17:04:21 -070030DATA_DIR = os.path.join(os.path.dirname(__file__), "..", "data")
Hiranya Jayathilaka23c88f72017-12-05 09:29:59 -080031
Bu Sun Kim9eec0912019-10-21 17:04:21 -070032AUTH_USER_JSON_FILE = os.path.join(DATA_DIR, "authorized_user.json")
Hiranya Jayathilaka23c88f72017-12-05 09:29:59 -080033
Bu Sun Kim9eec0912019-10-21 17:04:21 -070034with open(AUTH_USER_JSON_FILE, "r") as fh:
Hiranya Jayathilaka23c88f72017-12-05 09:29:59 -080035 AUTH_USER_INFO = json.load(fh)
36
37
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070038class TestCredentials(object):
Bu Sun Kim9eec0912019-10-21 17:04:21 -070039 TOKEN_URI = "https://example.com/oauth2/token"
40 REFRESH_TOKEN = "refresh_token"
41 CLIENT_ID = "client_id"
42 CLIENT_SECRET = "client_secret"
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070043
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070044 @classmethod
45 def make_credentials(cls):
46 return credentials.Credentials(
Bu Sun Kim9eec0912019-10-21 17:04:21 -070047 token=None,
48 refresh_token=cls.REFRESH_TOKEN,
49 token_uri=cls.TOKEN_URI,
50 client_id=cls.CLIENT_ID,
51 client_secret=cls.CLIENT_SECRET,
52 )
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070053
54 def test_default_state(self):
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070055 credentials = self.make_credentials()
56 assert not credentials.valid
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070057 # Expiration hasn't been set yet
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070058 assert not credentials.expired
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070059 # Scopes aren't required for these credentials
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070060 assert not credentials.requires_scopes
Jon Wayne Parrott2d0549a2017-03-01 09:27:16 -080061 # Test properties
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070062 assert credentials.refresh_token == self.REFRESH_TOKEN
63 assert credentials.token_uri == self.TOKEN_URI
64 assert credentials.client_id == self.CLIENT_ID
65 assert credentials.client_secret == self.CLIENT_SECRET
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070066
Bu Sun Kim9eec0912019-10-21 17:04:21 -070067 @mock.patch("google.oauth2._client.refresh_grant", autospec=True)
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070068 @mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -070069 "google.auth._helpers.utcnow",
70 return_value=datetime.datetime.min + _helpers.CLOCK_SKEW,
71 )
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070072 def test_refresh_success(self, unused_utcnow, refresh_grant):
Bu Sun Kim9eec0912019-10-21 17:04:21 -070073 token = "token"
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070074 expiry = _helpers.utcnow() + datetime.timedelta(seconds=500)
Bu Sun Kim9eec0912019-10-21 17:04:21 -070075 grant_response = {"id_token": mock.sentinel.id_token}
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070076 refresh_grant.return_value = (
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070077 # Access token
78 token,
79 # New refresh token
80 None,
81 # Expiry,
82 expiry,
83 # Extra data
Bu Sun Kim9eec0912019-10-21 17:04:21 -070084 grant_response,
85 )
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070086
87 request = mock.create_autospec(transport.Request)
88 credentials = self.make_credentials()
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070089
90 # Refresh credentials
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070091 credentials.refresh(request)
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070092
93 # Check jwt grant call.
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070094 refresh_grant.assert_called_with(
Bu Sun Kim9eec0912019-10-21 17:04:21 -070095 request,
96 self.TOKEN_URI,
97 self.REFRESH_TOKEN,
98 self.CLIENT_ID,
99 self.CLIENT_SECRET,
100 None,
101 )
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -0700102
103 # Check that the credentials have the token and expiry
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700104 assert credentials.token == token
105 assert credentials.expiry == expiry
106 assert credentials.id_token == mock.sentinel.id_token
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -0700107
108 # Check that the credentials are valid (have a token and are not
109 # expired)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700110 assert credentials.valid
Hiranya Jayathilaka23c88f72017-12-05 09:29:59 -0800111
Thea Flowers118c0482018-05-24 13:34:07 -0700112 def test_refresh_no_refresh_token(self):
113 request = mock.create_autospec(transport.Request)
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700114 credentials_ = credentials.Credentials(token=None, refresh_token=None)
Thea Flowers118c0482018-05-24 13:34:07 -0700115
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700116 with pytest.raises(exceptions.RefreshError, match="necessary fields"):
Thea Flowers118c0482018-05-24 13:34:07 -0700117 credentials_.refresh(request)
118
119 request.assert_not_called()
120
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700121 @mock.patch("google.oauth2._client.refresh_grant", autospec=True)
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400122 @mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700123 "google.auth._helpers.utcnow",
124 return_value=datetime.datetime.min + _helpers.CLOCK_SKEW,
125 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400126 def test_credentials_with_scopes_requested_refresh_success(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700127 self, unused_utcnow, refresh_grant
128 ):
129 scopes = ["email", "profile"]
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -0700130 default_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700131 token = "token"
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400132 expiry = _helpers.utcnow() + datetime.timedelta(seconds=500)
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700133 grant_response = {"id_token": mock.sentinel.id_token}
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400134 refresh_grant.return_value = (
135 # Access token
136 token,
137 # New refresh token
138 None,
139 # Expiry,
140 expiry,
141 # Extra data
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700142 grant_response,
143 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400144
145 request = mock.create_autospec(transport.Request)
146 creds = credentials.Credentials(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700147 token=None,
148 refresh_token=self.REFRESH_TOKEN,
149 token_uri=self.TOKEN_URI,
150 client_id=self.CLIENT_ID,
151 client_secret=self.CLIENT_SECRET,
152 scopes=scopes,
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -0700153 default_scopes=default_scopes,
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700154 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400155
156 # Refresh credentials
157 creds.refresh(request)
158
159 # Check jwt grant call.
160 refresh_grant.assert_called_with(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700161 request,
162 self.TOKEN_URI,
163 self.REFRESH_TOKEN,
164 self.CLIENT_ID,
165 self.CLIENT_SECRET,
166 scopes,
167 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400168
169 # Check that the credentials have the token and expiry
170 assert creds.token == token
171 assert creds.expiry == expiry
172 assert creds.id_token == mock.sentinel.id_token
173 assert creds.has_scopes(scopes)
174
175 # Check that the credentials are valid (have a token and are not
176 # expired.)
177 assert creds.valid
178
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700179 @mock.patch("google.oauth2._client.refresh_grant", autospec=True)
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400180 @mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700181 "google.auth._helpers.utcnow",
182 return_value=datetime.datetime.min + _helpers.CLOCK_SKEW,
183 )
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -0700184 def test_credentials_with_only_default_scopes_requested(
185 self, unused_utcnow, refresh_grant
186 ):
187 default_scopes = ["email", "profile"]
188 token = "token"
189 expiry = _helpers.utcnow() + datetime.timedelta(seconds=500)
190 grant_response = {"id_token": mock.sentinel.id_token}
191 refresh_grant.return_value = (
192 # Access token
193 token,
194 # New refresh token
195 None,
196 # Expiry,
197 expiry,
198 # Extra data
199 grant_response,
200 )
201
202 request = mock.create_autospec(transport.Request)
203 creds = credentials.Credentials(
204 token=None,
205 refresh_token=self.REFRESH_TOKEN,
206 token_uri=self.TOKEN_URI,
207 client_id=self.CLIENT_ID,
208 client_secret=self.CLIENT_SECRET,
209 default_scopes=default_scopes,
210 )
211
212 # Refresh credentials
213 creds.refresh(request)
214
215 # Check jwt grant call.
216 refresh_grant.assert_called_with(
217 request,
218 self.TOKEN_URI,
219 self.REFRESH_TOKEN,
220 self.CLIENT_ID,
221 self.CLIENT_SECRET,
222 default_scopes,
223 )
224
225 # Check that the credentials have the token and expiry
226 assert creds.token == token
227 assert creds.expiry == expiry
228 assert creds.id_token == mock.sentinel.id_token
229 assert creds.has_scopes(default_scopes)
230
231 # Check that the credentials are valid (have a token and are not
232 # expired.)
233 assert creds.valid
234
235 @mock.patch("google.oauth2._client.refresh_grant", autospec=True)
236 @mock.patch(
237 "google.auth._helpers.utcnow",
238 return_value=datetime.datetime.min + _helpers.CLOCK_SKEW,
239 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400240 def test_credentials_with_scopes_returned_refresh_success(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700241 self, unused_utcnow, refresh_grant
242 ):
243 scopes = ["email", "profile"]
244 token = "token"
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400245 expiry = _helpers.utcnow() + datetime.timedelta(seconds=500)
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700246 grant_response = {
247 "id_token": mock.sentinel.id_token,
248 "scopes": " ".join(scopes),
249 }
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400250 refresh_grant.return_value = (
251 # Access token
252 token,
253 # New refresh token
254 None,
255 # Expiry,
256 expiry,
257 # Extra data
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700258 grant_response,
259 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400260
261 request = mock.create_autospec(transport.Request)
262 creds = credentials.Credentials(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700263 token=None,
264 refresh_token=self.REFRESH_TOKEN,
265 token_uri=self.TOKEN_URI,
266 client_id=self.CLIENT_ID,
267 client_secret=self.CLIENT_SECRET,
268 scopes=scopes,
269 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400270
271 # Refresh credentials
272 creds.refresh(request)
273
274 # Check jwt grant call.
275 refresh_grant.assert_called_with(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700276 request,
277 self.TOKEN_URI,
278 self.REFRESH_TOKEN,
279 self.CLIENT_ID,
280 self.CLIENT_SECRET,
281 scopes,
282 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400283
284 # Check that the credentials have the token and expiry
285 assert creds.token == token
286 assert creds.expiry == expiry
287 assert creds.id_token == mock.sentinel.id_token
288 assert creds.has_scopes(scopes)
289
290 # Check that the credentials are valid (have a token and are not
291 # expired.)
292 assert creds.valid
293
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700294 @mock.patch("google.oauth2._client.refresh_grant", autospec=True)
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400295 @mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700296 "google.auth._helpers.utcnow",
297 return_value=datetime.datetime.min + _helpers.CLOCK_SKEW,
298 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400299 def test_credentials_with_scopes_refresh_failure_raises_refresh_error(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700300 self, unused_utcnow, refresh_grant
301 ):
302 scopes = ["email", "profile"]
303 scopes_returned = ["email"]
304 token = "token"
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400305 expiry = _helpers.utcnow() + datetime.timedelta(seconds=500)
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700306 grant_response = {
307 "id_token": mock.sentinel.id_token,
308 "scopes": " ".join(scopes_returned),
309 }
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400310 refresh_grant.return_value = (
311 # Access token
312 token,
313 # New refresh token
314 None,
315 # Expiry,
316 expiry,
317 # Extra data
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700318 grant_response,
319 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400320
321 request = mock.create_autospec(transport.Request)
322 creds = credentials.Credentials(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700323 token=None,
324 refresh_token=self.REFRESH_TOKEN,
325 token_uri=self.TOKEN_URI,
326 client_id=self.CLIENT_ID,
327 client_secret=self.CLIENT_SECRET,
328 scopes=scopes,
329 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400330
331 # Refresh credentials
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700332 with pytest.raises(
333 exceptions.RefreshError, match="Not all requested scopes were granted"
334 ):
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400335 creds.refresh(request)
336
337 # Check jwt grant call.
338 refresh_grant.assert_called_with(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700339 request,
340 self.TOKEN_URI,
341 self.REFRESH_TOKEN,
342 self.CLIENT_ID,
343 self.CLIENT_SECRET,
344 scopes,
345 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400346
347 # Check that the credentials have the token and expiry
348 assert creds.token == token
349 assert creds.expiry == expiry
350 assert creds.id_token == mock.sentinel.id_token
351 assert creds.has_scopes(scopes)
352
353 # Check that the credentials are valid (have a token and are not
354 # expired.)
355 assert creds.valid
356
Bu Sun Kim32d71a52019-12-18 11:30:46 -0800357 def test_apply_with_quota_project_id(self):
358 creds = credentials.Credentials(
359 token="token",
360 refresh_token=self.REFRESH_TOKEN,
361 token_uri=self.TOKEN_URI,
362 client_id=self.CLIENT_ID,
363 client_secret=self.CLIENT_SECRET,
364 quota_project_id="quota-project-123",
365 )
366
367 headers = {}
368 creds.apply(headers)
369 assert headers["x-goog-user-project"] == "quota-project-123"
Bu Sun Kim18d5ae62020-07-21 13:44:03 -0700370 assert "token" in headers["authorization"]
Bu Sun Kim32d71a52019-12-18 11:30:46 -0800371
372 def test_apply_with_no_quota_project_id(self):
373 creds = credentials.Credentials(
374 token="token",
375 refresh_token=self.REFRESH_TOKEN,
376 token_uri=self.TOKEN_URI,
377 client_id=self.CLIENT_ID,
378 client_secret=self.CLIENT_SECRET,
379 )
380
381 headers = {}
382 creds.apply(headers)
383 assert "x-goog-user-project" not in headers
Bu Sun Kim18d5ae62020-07-21 13:44:03 -0700384 assert "token" in headers["authorization"]
Bu Sun Kim32d71a52019-12-18 11:30:46 -0800385
Bu Sun Kimb12488c2020-06-10 13:44:07 -0700386 def test_with_quota_project(self):
387 creds = credentials.Credentials(
388 token="token",
389 refresh_token=self.REFRESH_TOKEN,
390 token_uri=self.TOKEN_URI,
391 client_id=self.CLIENT_ID,
392 client_secret=self.CLIENT_SECRET,
393 quota_project_id="quota-project-123",
394 )
395
396 new_creds = creds.with_quota_project("new-project-456")
397 assert new_creds.quota_project_id == "new-project-456"
398 headers = {}
399 creds.apply(headers)
400 assert "x-goog-user-project" in headers
401
Hiranya Jayathilaka23c88f72017-12-05 09:29:59 -0800402 def test_from_authorized_user_info(self):
403 info = AUTH_USER_INFO.copy()
404
405 creds = credentials.Credentials.from_authorized_user_info(info)
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700406 assert creds.client_secret == info["client_secret"]
407 assert creds.client_id == info["client_id"]
408 assert creds.refresh_token == info["refresh_token"]
Hiranya Jayathilaka23c88f72017-12-05 09:29:59 -0800409 assert creds.token_uri == credentials._GOOGLE_OAUTH2_TOKEN_ENDPOINT
410 assert creds.scopes is None
411
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700412 scopes = ["email", "profile"]
413 creds = credentials.Credentials.from_authorized_user_info(info, scopes)
414 assert creds.client_secret == info["client_secret"]
415 assert creds.client_id == info["client_id"]
416 assert creds.refresh_token == info["refresh_token"]
Hiranya Jayathilaka23c88f72017-12-05 09:29:59 -0800417 assert creds.token_uri == credentials._GOOGLE_OAUTH2_TOKEN_ENDPOINT
418 assert creds.scopes == scopes
419
wesley chund0e0aba2020-09-17 09:18:55 -0700420 info["scopes"] = "email" # single non-array scope from file
421 creds = credentials.Credentials.from_authorized_user_info(info)
422 assert creds.scopes == [info["scopes"]]
423
424 info["scopes"] = ["email", "profile"] # array scope from file
425 creds = credentials.Credentials.from_authorized_user_info(info)
426 assert creds.scopes == info["scopes"]
427
428 expiry = datetime.datetime(2020, 8, 14, 15, 54, 1)
429 info["expiry"] = expiry.isoformat() + "Z"
430 creds = credentials.Credentials.from_authorized_user_info(info)
431 assert creds.expiry == expiry
432 assert creds.expired
433
Hiranya Jayathilaka23c88f72017-12-05 09:29:59 -0800434 def test_from_authorized_user_file(self):
435 info = AUTH_USER_INFO.copy()
436
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700437 creds = credentials.Credentials.from_authorized_user_file(AUTH_USER_JSON_FILE)
438 assert creds.client_secret == info["client_secret"]
439 assert creds.client_id == info["client_id"]
440 assert creds.refresh_token == info["refresh_token"]
Hiranya Jayathilaka23c88f72017-12-05 09:29:59 -0800441 assert creds.token_uri == credentials._GOOGLE_OAUTH2_TOKEN_ENDPOINT
442 assert creds.scopes is None
443
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700444 scopes = ["email", "profile"]
Hiranya Jayathilaka23c88f72017-12-05 09:29:59 -0800445 creds = credentials.Credentials.from_authorized_user_file(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700446 AUTH_USER_JSON_FILE, scopes
447 )
448 assert creds.client_secret == info["client_secret"]
449 assert creds.client_id == info["client_id"]
450 assert creds.refresh_token == info["refresh_token"]
Hiranya Jayathilaka23c88f72017-12-05 09:29:59 -0800451 assert creds.token_uri == credentials._GOOGLE_OAUTH2_TOKEN_ENDPOINT
452 assert creds.scopes == scopes
patkasperbfb1f8c2019-12-05 22:03:44 +0100453
454 def test_to_json(self):
455 info = AUTH_USER_INFO.copy()
wesley chund0e0aba2020-09-17 09:18:55 -0700456 expiry = datetime.datetime(2020, 8, 14, 15, 54, 1)
457 info["expiry"] = expiry.isoformat() + "Z"
patkasperbfb1f8c2019-12-05 22:03:44 +0100458 creds = credentials.Credentials.from_authorized_user_info(info)
wesley chund0e0aba2020-09-17 09:18:55 -0700459 assert creds.expiry == expiry
patkasperbfb1f8c2019-12-05 22:03:44 +0100460
461 # Test with no `strip` arg
462 json_output = creds.to_json()
463 json_asdict = json.loads(json_output)
464 assert json_asdict.get("token") == creds.token
465 assert json_asdict.get("refresh_token") == creds.refresh_token
466 assert json_asdict.get("token_uri") == creds.token_uri
467 assert json_asdict.get("client_id") == creds.client_id
468 assert json_asdict.get("scopes") == creds.scopes
469 assert json_asdict.get("client_secret") == creds.client_secret
wesley chund0e0aba2020-09-17 09:18:55 -0700470 assert json_asdict.get("expiry") == info["expiry"]
patkasperbfb1f8c2019-12-05 22:03:44 +0100471
472 # Test with a `strip` arg
473 json_output = creds.to_json(strip=["client_secret"])
474 json_asdict = json.loads(json_output)
475 assert json_asdict.get("token") == creds.token
476 assert json_asdict.get("refresh_token") == creds.refresh_token
477 assert json_asdict.get("token_uri") == creds.token_uri
478 assert json_asdict.get("client_id") == creds.client_id
479 assert json_asdict.get("scopes") == creds.scopes
480 assert json_asdict.get("client_secret") is None
Bu Sun Kim32d71a52019-12-18 11:30:46 -0800481
wesley chund0e0aba2020-09-17 09:18:55 -0700482 # Test with no expiry
483 creds.expiry = None
484 json_output = creds.to_json()
485 json_asdict = json.loads(json_output)
486 assert json_asdict.get("expiry") is None
487
Bu Sun Kim32d71a52019-12-18 11:30:46 -0800488 def test_pickle_and_unpickle(self):
489 creds = self.make_credentials()
490 unpickled = pickle.loads(pickle.dumps(creds))
491
492 # make sure attributes aren't lost during pickling
493 assert list(creds.__dict__).sort() == list(unpickled.__dict__).sort()
494
495 for attr in list(creds.__dict__):
496 assert getattr(creds, attr) == getattr(unpickled, attr)
497
498 def test_pickle_with_missing_attribute(self):
499 creds = self.make_credentials()
500
501 # remove an optional attribute before pickling
502 # this mimics a pickle created with a previous class definition with
503 # fewer attributes
504 del creds.__dict__["_quota_project_id"]
505
506 unpickled = pickle.loads(pickle.dumps(creds))
507
508 # Attribute should be initialized by `__setstate__`
509 assert unpickled.quota_project_id is None
510
511 # pickles are not compatible across versions
512 @pytest.mark.skipif(
513 sys.version_info < (3, 5),
514 reason="pickle file can only be loaded with Python >= 3.5",
515 )
516 def test_unpickle_old_credentials_pickle(self):
517 # make sure a credentials file pickled with an older
518 # library version (google-auth==1.5.1) can be unpickled
519 with open(
520 os.path.join(DATA_DIR, "old_oauth_credentials_py3.pickle"), "rb"
521 ) as f:
522 credentials = pickle.load(f)
523 assert credentials.quota_project_id is None
arithmetic1728772dac62020-03-27 14:34:13 -0700524
525
526class TestUserAccessTokenCredentials(object):
527 def test_instance(self):
528 cred = credentials.UserAccessTokenCredentials()
529 assert cred._account is None
530
531 cred = cred.with_account("account")
532 assert cred._account == "account"
533
534 @mock.patch("google.auth._cloud_sdk.get_auth_access_token", autospec=True)
535 def test_refresh(self, get_auth_access_token):
536 get_auth_access_token.return_value = "access_token"
537 cred = credentials.UserAccessTokenCredentials()
538 cred.refresh(None)
539 assert cred.token == "access_token"
540
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700541 def test_with_quota_project(self):
542 cred = credentials.UserAccessTokenCredentials()
543 quota_project_cred = cred.with_quota_project("project-foo")
544
545 assert quota_project_cred._quota_project_id == "project-foo"
546 assert quota_project_cred._account == cred._account
547
arithmetic1728772dac62020-03-27 14:34:13 -0700548 @mock.patch(
549 "google.oauth2.credentials.UserAccessTokenCredentials.apply", autospec=True
550 )
551 @mock.patch(
552 "google.oauth2.credentials.UserAccessTokenCredentials.refresh", autospec=True
553 )
554 def test_before_request(self, refresh, apply):
555 cred = credentials.UserAccessTokenCredentials()
556 cred.before_request(mock.Mock(), "GET", "https://example.com", {})
557 refresh.assert_called()
558 apply.assert_called()