blob: 4a387a58e068fc398e8f40cf7e0b483fa9bbf46f [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"
arithmetic172882293fe2021-04-14 11:22:13 -070041 RAPT_TOKEN = "rapt_token"
Bu Sun Kim9eec0912019-10-21 17:04:21 -070042 CLIENT_ID = "client_id"
43 CLIENT_SECRET = "client_secret"
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070044
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070045 @classmethod
46 def make_credentials(cls):
47 return credentials.Credentials(
Bu Sun Kim9eec0912019-10-21 17:04:21 -070048 token=None,
49 refresh_token=cls.REFRESH_TOKEN,
50 token_uri=cls.TOKEN_URI,
51 client_id=cls.CLIENT_ID,
52 client_secret=cls.CLIENT_SECRET,
arithmetic172882293fe2021-04-14 11:22:13 -070053 rapt_token=cls.RAPT_TOKEN,
Bu Sun Kim9eec0912019-10-21 17:04:21 -070054 )
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070055
56 def test_default_state(self):
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070057 credentials = self.make_credentials()
58 assert not credentials.valid
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070059 # Expiration hasn't been set yet
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070060 assert not credentials.expired
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070061 # Scopes aren't required for these credentials
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070062 assert not credentials.requires_scopes
Jon Wayne Parrott2d0549a2017-03-01 09:27:16 -080063 # Test properties
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070064 assert credentials.refresh_token == self.REFRESH_TOKEN
65 assert credentials.token_uri == self.TOKEN_URI
66 assert credentials.client_id == self.CLIENT_ID
67 assert credentials.client_secret == self.CLIENT_SECRET
arithmetic172882293fe2021-04-14 11:22:13 -070068 assert credentials.rapt_token == self.RAPT_TOKEN
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070069
arithmetic172882293fe2021-04-14 11:22:13 -070070 @mock.patch("google.oauth2.reauth.refresh_grant", autospec=True)
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070071 @mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -070072 "google.auth._helpers.utcnow",
73 return_value=datetime.datetime.min + _helpers.CLOCK_SKEW,
74 )
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070075 def test_refresh_success(self, unused_utcnow, refresh_grant):
Bu Sun Kim9eec0912019-10-21 17:04:21 -070076 token = "token"
arithmetic172882293fe2021-04-14 11:22:13 -070077 new_rapt_token = "new_rapt_token"
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070078 expiry = _helpers.utcnow() + datetime.timedelta(seconds=500)
Bu Sun Kim9eec0912019-10-21 17:04:21 -070079 grant_response = {"id_token": mock.sentinel.id_token}
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070080 refresh_grant.return_value = (
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070081 # Access token
82 token,
83 # New refresh token
84 None,
85 # Expiry,
86 expiry,
87 # Extra data
Bu Sun Kim9eec0912019-10-21 17:04:21 -070088 grant_response,
arithmetic172882293fe2021-04-14 11:22:13 -070089 # rapt_token
90 new_rapt_token,
Bu Sun Kim9eec0912019-10-21 17:04:21 -070091 )
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070092
93 request = mock.create_autospec(transport.Request)
94 credentials = self.make_credentials()
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070095
96 # Refresh credentials
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -070097 credentials.refresh(request)
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -070098
99 # Check jwt grant call.
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700100 refresh_grant.assert_called_with(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700101 request,
102 self.TOKEN_URI,
103 self.REFRESH_TOKEN,
104 self.CLIENT_ID,
105 self.CLIENT_SECRET,
106 None,
arithmetic172882293fe2021-04-14 11:22:13 -0700107 self.RAPT_TOKEN,
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700108 )
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -0700109
110 # Check that the credentials have the token and expiry
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700111 assert credentials.token == token
112 assert credentials.expiry == expiry
113 assert credentials.id_token == mock.sentinel.id_token
arithmetic172882293fe2021-04-14 11:22:13 -0700114 assert credentials.rapt_token == new_rapt_token
Jon Wayne Parrott10ec7e92016-10-17 10:46:38 -0700115
116 # Check that the credentials are valid (have a token and are not
117 # expired)
Jon Wayne Parrott78fec2c2017-06-30 10:25:08 -0700118 assert credentials.valid
Hiranya Jayathilaka23c88f72017-12-05 09:29:59 -0800119
Thea Flowers118c0482018-05-24 13:34:07 -0700120 def test_refresh_no_refresh_token(self):
121 request = mock.create_autospec(transport.Request)
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700122 credentials_ = credentials.Credentials(token=None, refresh_token=None)
Thea Flowers118c0482018-05-24 13:34:07 -0700123
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700124 with pytest.raises(exceptions.RefreshError, match="necessary fields"):
Thea Flowers118c0482018-05-24 13:34:07 -0700125 credentials_.refresh(request)
126
127 request.assert_not_called()
128
arithmetic172882293fe2021-04-14 11:22:13 -0700129 @mock.patch("google.oauth2.reauth.refresh_grant", autospec=True)
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400130 @mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700131 "google.auth._helpers.utcnow",
132 return_value=datetime.datetime.min + _helpers.CLOCK_SKEW,
133 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400134 def test_credentials_with_scopes_requested_refresh_success(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700135 self, unused_utcnow, refresh_grant
136 ):
137 scopes = ["email", "profile"]
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -0700138 default_scopes = ["https://www.googleapis.com/auth/cloud-platform"]
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700139 token = "token"
arithmetic172882293fe2021-04-14 11:22:13 -0700140 new_rapt_token = "new_rapt_token"
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400141 expiry = _helpers.utcnow() + datetime.timedelta(seconds=500)
arithmetic172882293fe2021-04-14 11:22:13 -0700142 grant_response = {"id_token": mock.sentinel.id_token, "scope": "email profile"}
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400143 refresh_grant.return_value = (
144 # Access token
145 token,
146 # New refresh token
147 None,
148 # Expiry,
149 expiry,
150 # Extra data
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700151 grant_response,
arithmetic172882293fe2021-04-14 11:22:13 -0700152 # rapt token
153 new_rapt_token,
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700154 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400155
156 request = mock.create_autospec(transport.Request)
157 creds = credentials.Credentials(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700158 token=None,
159 refresh_token=self.REFRESH_TOKEN,
160 token_uri=self.TOKEN_URI,
161 client_id=self.CLIENT_ID,
162 client_secret=self.CLIENT_SECRET,
163 scopes=scopes,
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -0700164 default_scopes=default_scopes,
arithmetic172882293fe2021-04-14 11:22:13 -0700165 rapt_token=self.RAPT_TOKEN,
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700166 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400167
168 # Refresh credentials
169 creds.refresh(request)
170
171 # Check jwt grant call.
172 refresh_grant.assert_called_with(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700173 request,
174 self.TOKEN_URI,
175 self.REFRESH_TOKEN,
176 self.CLIENT_ID,
177 self.CLIENT_SECRET,
178 scopes,
arithmetic172882293fe2021-04-14 11:22:13 -0700179 self.RAPT_TOKEN,
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700180 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400181
182 # Check that the credentials have the token and expiry
183 assert creds.token == token
184 assert creds.expiry == expiry
185 assert creds.id_token == mock.sentinel.id_token
186 assert creds.has_scopes(scopes)
arithmetic172882293fe2021-04-14 11:22:13 -0700187 assert creds.rapt_token == new_rapt_token
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400188
189 # Check that the credentials are valid (have a token and are not
190 # expired.)
191 assert creds.valid
192
arithmetic172882293fe2021-04-14 11:22:13 -0700193 @mock.patch("google.oauth2.reauth.refresh_grant", autospec=True)
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400194 @mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700195 "google.auth._helpers.utcnow",
196 return_value=datetime.datetime.min + _helpers.CLOCK_SKEW,
197 )
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -0700198 def test_credentials_with_only_default_scopes_requested(
199 self, unused_utcnow, refresh_grant
200 ):
201 default_scopes = ["email", "profile"]
202 token = "token"
arithmetic172882293fe2021-04-14 11:22:13 -0700203 new_rapt_token = "new_rapt_token"
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -0700204 expiry = _helpers.utcnow() + datetime.timedelta(seconds=500)
205 grant_response = {"id_token": mock.sentinel.id_token}
206 refresh_grant.return_value = (
207 # Access token
208 token,
209 # New refresh token
210 None,
211 # Expiry,
212 expiry,
213 # Extra data
214 grant_response,
arithmetic172882293fe2021-04-14 11:22:13 -0700215 # rapt token
216 new_rapt_token,
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -0700217 )
218
219 request = mock.create_autospec(transport.Request)
220 creds = credentials.Credentials(
221 token=None,
222 refresh_token=self.REFRESH_TOKEN,
223 token_uri=self.TOKEN_URI,
224 client_id=self.CLIENT_ID,
225 client_secret=self.CLIENT_SECRET,
226 default_scopes=default_scopes,
arithmetic172882293fe2021-04-14 11:22:13 -0700227 rapt_token=self.RAPT_TOKEN,
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -0700228 )
229
230 # Refresh credentials
231 creds.refresh(request)
232
233 # Check jwt grant call.
234 refresh_grant.assert_called_with(
235 request,
236 self.TOKEN_URI,
237 self.REFRESH_TOKEN,
238 self.CLIENT_ID,
239 self.CLIENT_SECRET,
240 default_scopes,
arithmetic172882293fe2021-04-14 11:22:13 -0700241 self.RAPT_TOKEN,
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -0700242 )
243
244 # Check that the credentials have the token and expiry
245 assert creds.token == token
246 assert creds.expiry == expiry
247 assert creds.id_token == mock.sentinel.id_token
248 assert creds.has_scopes(default_scopes)
arithmetic172882293fe2021-04-14 11:22:13 -0700249 assert creds.rapt_token == new_rapt_token
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -0700250
251 # Check that the credentials are valid (have a token and are not
252 # expired.)
253 assert creds.valid
254
arithmetic172882293fe2021-04-14 11:22:13 -0700255 @mock.patch("google.oauth2.reauth.refresh_grant", autospec=True)
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -0700256 @mock.patch(
257 "google.auth._helpers.utcnow",
258 return_value=datetime.datetime.min + _helpers.CLOCK_SKEW,
259 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400260 def test_credentials_with_scopes_returned_refresh_success(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700261 self, unused_utcnow, refresh_grant
262 ):
263 scopes = ["email", "profile"]
264 token = "token"
arithmetic172882293fe2021-04-14 11:22:13 -0700265 new_rapt_token = "new_rapt_token"
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400266 expiry = _helpers.utcnow() + datetime.timedelta(seconds=500)
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700267 grant_response = {
268 "id_token": mock.sentinel.id_token,
269 "scopes": " ".join(scopes),
270 }
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400271 refresh_grant.return_value = (
272 # Access token
273 token,
274 # New refresh token
275 None,
276 # Expiry,
277 expiry,
278 # Extra data
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700279 grant_response,
arithmetic172882293fe2021-04-14 11:22:13 -0700280 # rapt token
281 new_rapt_token,
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700282 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400283
284 request = mock.create_autospec(transport.Request)
285 creds = credentials.Credentials(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700286 token=None,
287 refresh_token=self.REFRESH_TOKEN,
288 token_uri=self.TOKEN_URI,
289 client_id=self.CLIENT_ID,
290 client_secret=self.CLIENT_SECRET,
291 scopes=scopes,
arithmetic172882293fe2021-04-14 11:22:13 -0700292 rapt_token=self.RAPT_TOKEN,
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700293 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400294
295 # Refresh credentials
296 creds.refresh(request)
297
298 # Check jwt grant call.
299 refresh_grant.assert_called_with(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700300 request,
301 self.TOKEN_URI,
302 self.REFRESH_TOKEN,
303 self.CLIENT_ID,
304 self.CLIENT_SECRET,
305 scopes,
arithmetic172882293fe2021-04-14 11:22:13 -0700306 self.RAPT_TOKEN,
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700307 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400308
309 # Check that the credentials have the token and expiry
310 assert creds.token == token
311 assert creds.expiry == expiry
312 assert creds.id_token == mock.sentinel.id_token
313 assert creds.has_scopes(scopes)
arithmetic172882293fe2021-04-14 11:22:13 -0700314 assert creds.rapt_token == new_rapt_token
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400315
316 # Check that the credentials are valid (have a token and are not
317 # expired.)
318 assert creds.valid
319
arithmetic172882293fe2021-04-14 11:22:13 -0700320 @mock.patch("google.oauth2.reauth.refresh_grant", autospec=True)
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400321 @mock.patch(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700322 "google.auth._helpers.utcnow",
323 return_value=datetime.datetime.min + _helpers.CLOCK_SKEW,
324 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400325 def test_credentials_with_scopes_refresh_failure_raises_refresh_error(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700326 self, unused_utcnow, refresh_grant
327 ):
328 scopes = ["email", "profile"]
329 scopes_returned = ["email"]
330 token = "token"
arithmetic172882293fe2021-04-14 11:22:13 -0700331 new_rapt_token = "new_rapt_token"
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400332 expiry = _helpers.utcnow() + datetime.timedelta(seconds=500)
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700333 grant_response = {
334 "id_token": mock.sentinel.id_token,
arithmetic172882293fe2021-04-14 11:22:13 -0700335 "scope": " ".join(scopes_returned),
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700336 }
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400337 refresh_grant.return_value = (
338 # Access token
339 token,
340 # New refresh token
341 None,
342 # Expiry,
343 expiry,
344 # Extra data
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700345 grant_response,
arithmetic172882293fe2021-04-14 11:22:13 -0700346 # rapt token
347 new_rapt_token,
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700348 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400349
350 request = mock.create_autospec(transport.Request)
351 creds = credentials.Credentials(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700352 token=None,
353 refresh_token=self.REFRESH_TOKEN,
354 token_uri=self.TOKEN_URI,
355 client_id=self.CLIENT_ID,
356 client_secret=self.CLIENT_SECRET,
357 scopes=scopes,
arithmetic172882293fe2021-04-14 11:22:13 -0700358 rapt_token=self.RAPT_TOKEN,
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700359 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400360
361 # Refresh credentials
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700362 with pytest.raises(
363 exceptions.RefreshError, match="Not all requested scopes were granted"
364 ):
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400365 creds.refresh(request)
366
367 # Check jwt grant call.
368 refresh_grant.assert_called_with(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700369 request,
370 self.TOKEN_URI,
371 self.REFRESH_TOKEN,
372 self.CLIENT_ID,
373 self.CLIENT_SECRET,
374 scopes,
arithmetic172882293fe2021-04-14 11:22:13 -0700375 self.RAPT_TOKEN,
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700376 )
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400377
378 # Check that the credentials have the token and expiry
379 assert creds.token == token
380 assert creds.expiry == expiry
381 assert creds.id_token == mock.sentinel.id_token
382 assert creds.has_scopes(scopes)
arithmetic172882293fe2021-04-14 11:22:13 -0700383 assert creds.rapt_token == new_rapt_token
Eugene W. Foley49a18c42019-05-22 13:50:38 -0400384
385 # Check that the credentials are valid (have a token and are not
386 # expired.)
387 assert creds.valid
388
Bu Sun Kim32d71a52019-12-18 11:30:46 -0800389 def test_apply_with_quota_project_id(self):
390 creds = credentials.Credentials(
391 token="token",
392 refresh_token=self.REFRESH_TOKEN,
393 token_uri=self.TOKEN_URI,
394 client_id=self.CLIENT_ID,
395 client_secret=self.CLIENT_SECRET,
396 quota_project_id="quota-project-123",
397 )
398
399 headers = {}
400 creds.apply(headers)
401 assert headers["x-goog-user-project"] == "quota-project-123"
Bu Sun Kim18d5ae62020-07-21 13:44:03 -0700402 assert "token" in headers["authorization"]
Bu Sun Kim32d71a52019-12-18 11:30:46 -0800403
404 def test_apply_with_no_quota_project_id(self):
405 creds = credentials.Credentials(
406 token="token",
407 refresh_token=self.REFRESH_TOKEN,
408 token_uri=self.TOKEN_URI,
409 client_id=self.CLIENT_ID,
410 client_secret=self.CLIENT_SECRET,
411 )
412
413 headers = {}
414 creds.apply(headers)
415 assert "x-goog-user-project" not in headers
Bu Sun Kim18d5ae62020-07-21 13:44:03 -0700416 assert "token" in headers["authorization"]
Bu Sun Kim32d71a52019-12-18 11:30:46 -0800417
Bu Sun Kimb12488c2020-06-10 13:44:07 -0700418 def test_with_quota_project(self):
419 creds = credentials.Credentials(
420 token="token",
421 refresh_token=self.REFRESH_TOKEN,
422 token_uri=self.TOKEN_URI,
423 client_id=self.CLIENT_ID,
424 client_secret=self.CLIENT_SECRET,
425 quota_project_id="quota-project-123",
426 )
427
428 new_creds = creds.with_quota_project("new-project-456")
429 assert new_creds.quota_project_id == "new-project-456"
430 headers = {}
431 creds.apply(headers)
432 assert "x-goog-user-project" in headers
433
Hiranya Jayathilaka23c88f72017-12-05 09:29:59 -0800434 def test_from_authorized_user_info(self):
435 info = AUTH_USER_INFO.copy()
436
437 creds = credentials.Credentials.from_authorized_user_info(info)
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700438 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"]
445 creds = credentials.Credentials.from_authorized_user_info(info, scopes)
446 assert creds.client_secret == info["client_secret"]
447 assert creds.client_id == info["client_id"]
448 assert creds.refresh_token == info["refresh_token"]
Hiranya Jayathilaka23c88f72017-12-05 09:29:59 -0800449 assert creds.token_uri == credentials._GOOGLE_OAUTH2_TOKEN_ENDPOINT
450 assert creds.scopes == scopes
451
wesley chund0e0aba2020-09-17 09:18:55 -0700452 info["scopes"] = "email" # single non-array scope from file
453 creds = credentials.Credentials.from_authorized_user_info(info)
454 assert creds.scopes == [info["scopes"]]
455
456 info["scopes"] = ["email", "profile"] # array scope from file
457 creds = credentials.Credentials.from_authorized_user_info(info)
458 assert creds.scopes == info["scopes"]
459
460 expiry = datetime.datetime(2020, 8, 14, 15, 54, 1)
461 info["expiry"] = expiry.isoformat() + "Z"
462 creds = credentials.Credentials.from_authorized_user_info(info)
463 assert creds.expiry == expiry
464 assert creds.expired
465
Hiranya Jayathilaka23c88f72017-12-05 09:29:59 -0800466 def test_from_authorized_user_file(self):
467 info = AUTH_USER_INFO.copy()
468
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700469 creds = credentials.Credentials.from_authorized_user_file(AUTH_USER_JSON_FILE)
470 assert creds.client_secret == info["client_secret"]
471 assert creds.client_id == info["client_id"]
472 assert creds.refresh_token == info["refresh_token"]
Hiranya Jayathilaka23c88f72017-12-05 09:29:59 -0800473 assert creds.token_uri == credentials._GOOGLE_OAUTH2_TOKEN_ENDPOINT
474 assert creds.scopes is None
475
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700476 scopes = ["email", "profile"]
Hiranya Jayathilaka23c88f72017-12-05 09:29:59 -0800477 creds = credentials.Credentials.from_authorized_user_file(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700478 AUTH_USER_JSON_FILE, scopes
479 )
480 assert creds.client_secret == info["client_secret"]
481 assert creds.client_id == info["client_id"]
482 assert creds.refresh_token == info["refresh_token"]
Hiranya Jayathilaka23c88f72017-12-05 09:29:59 -0800483 assert creds.token_uri == credentials._GOOGLE_OAUTH2_TOKEN_ENDPOINT
484 assert creds.scopes == scopes
patkasperbfb1f8c2019-12-05 22:03:44 +0100485
486 def test_to_json(self):
487 info = AUTH_USER_INFO.copy()
wesley chund0e0aba2020-09-17 09:18:55 -0700488 expiry = datetime.datetime(2020, 8, 14, 15, 54, 1)
489 info["expiry"] = expiry.isoformat() + "Z"
patkasperbfb1f8c2019-12-05 22:03:44 +0100490 creds = credentials.Credentials.from_authorized_user_info(info)
wesley chund0e0aba2020-09-17 09:18:55 -0700491 assert creds.expiry == expiry
patkasperbfb1f8c2019-12-05 22:03:44 +0100492
493 # Test with no `strip` arg
494 json_output = creds.to_json()
495 json_asdict = json.loads(json_output)
496 assert json_asdict.get("token") == creds.token
497 assert json_asdict.get("refresh_token") == creds.refresh_token
498 assert json_asdict.get("token_uri") == creds.token_uri
499 assert json_asdict.get("client_id") == creds.client_id
500 assert json_asdict.get("scopes") == creds.scopes
501 assert json_asdict.get("client_secret") == creds.client_secret
wesley chund0e0aba2020-09-17 09:18:55 -0700502 assert json_asdict.get("expiry") == info["expiry"]
patkasperbfb1f8c2019-12-05 22:03:44 +0100503
504 # Test with a `strip` arg
505 json_output = creds.to_json(strip=["client_secret"])
506 json_asdict = json.loads(json_output)
507 assert json_asdict.get("token") == creds.token
508 assert json_asdict.get("refresh_token") == creds.refresh_token
509 assert json_asdict.get("token_uri") == creds.token_uri
510 assert json_asdict.get("client_id") == creds.client_id
511 assert json_asdict.get("scopes") == creds.scopes
512 assert json_asdict.get("client_secret") is None
Bu Sun Kim32d71a52019-12-18 11:30:46 -0800513
wesley chund0e0aba2020-09-17 09:18:55 -0700514 # Test with no expiry
515 creds.expiry = None
516 json_output = creds.to_json()
517 json_asdict = json.loads(json_output)
518 assert json_asdict.get("expiry") is None
519
Bu Sun Kim32d71a52019-12-18 11:30:46 -0800520 def test_pickle_and_unpickle(self):
521 creds = self.make_credentials()
522 unpickled = pickle.loads(pickle.dumps(creds))
523
524 # make sure attributes aren't lost during pickling
525 assert list(creds.__dict__).sort() == list(unpickled.__dict__).sort()
526
527 for attr in list(creds.__dict__):
528 assert getattr(creds, attr) == getattr(unpickled, attr)
529
530 def test_pickle_with_missing_attribute(self):
531 creds = self.make_credentials()
532
533 # remove an optional attribute before pickling
534 # this mimics a pickle created with a previous class definition with
535 # fewer attributes
536 del creds.__dict__["_quota_project_id"]
537
538 unpickled = pickle.loads(pickle.dumps(creds))
539
540 # Attribute should be initialized by `__setstate__`
541 assert unpickled.quota_project_id is None
542
543 # pickles are not compatible across versions
544 @pytest.mark.skipif(
545 sys.version_info < (3, 5),
546 reason="pickle file can only be loaded with Python >= 3.5",
547 )
548 def test_unpickle_old_credentials_pickle(self):
549 # make sure a credentials file pickled with an older
550 # library version (google-auth==1.5.1) can be unpickled
551 with open(
552 os.path.join(DATA_DIR, "old_oauth_credentials_py3.pickle"), "rb"
553 ) as f:
554 credentials = pickle.load(f)
555 assert credentials.quota_project_id is None
arithmetic1728772dac62020-03-27 14:34:13 -0700556
557
558class TestUserAccessTokenCredentials(object):
559 def test_instance(self):
560 cred = credentials.UserAccessTokenCredentials()
561 assert cred._account is None
562
563 cred = cred.with_account("account")
564 assert cred._account == "account"
565
566 @mock.patch("google.auth._cloud_sdk.get_auth_access_token", autospec=True)
567 def test_refresh(self, get_auth_access_token):
568 get_auth_access_token.return_value = "access_token"
569 cred = credentials.UserAccessTokenCredentials()
570 cred.refresh(None)
571 assert cred.token == "access_token"
572
Bu Sun Kim3dda7b22020-07-09 10:39:39 -0700573 def test_with_quota_project(self):
574 cred = credentials.UserAccessTokenCredentials()
575 quota_project_cred = cred.with_quota_project("project-foo")
576
577 assert quota_project_cred._quota_project_id == "project-foo"
578 assert quota_project_cred._account == cred._account
579
arithmetic1728772dac62020-03-27 14:34:13 -0700580 @mock.patch(
581 "google.oauth2.credentials.UserAccessTokenCredentials.apply", autospec=True
582 )
583 @mock.patch(
584 "google.oauth2.credentials.UserAccessTokenCredentials.refresh", autospec=True
585 )
586 def test_before_request(self, refresh, apply):
587 cred = credentials.UserAccessTokenCredentials()
588 cred.before_request(mock.Mock(), "GET", "https://example.com", {})
589 refresh.assert_called()
590 apply.assert_called()