blob: 0633b38c07cad24fec4bd837416f9e69863212e0 [file] [log] [blame]
C.J. Collier37141e42020-02-13 13:49:49 -08001# Copyright 2016 Google LLC
Jon Wayne Parrott71ce2a02016-10-14 14:08:10 -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
16
Tres Seaverb096a3d2017-10-30 16:12:37 -040017import pytest
18
Jon Wayne Parrotte60c1242017-03-23 16:00:24 -070019from google.auth import _helpers
Jon Wayne Parrott71ce2a02016-10-14 14:08:10 -070020from google.auth import credentials
21
22
23class CredentialsImpl(credentials.Credentials):
24 def refresh(self, request):
25 self.token = request
26
Bu Sun Kim3dda7b22020-07-09 10:39:39 -070027 def with_quota_project(self, quota_project_id):
28 raise NotImplementedError()
29
Jon Wayne Parrott71ce2a02016-10-14 14:08:10 -070030
31def test_credentials_constructor():
32 credentials = CredentialsImpl()
33 assert not credentials.token
34 assert not credentials.expiry
35 assert not credentials.expired
36 assert not credentials.valid
37
38
39def test_expired_and_valid():
40 credentials = CredentialsImpl()
Bu Sun Kim9eec0912019-10-21 17:04:21 -070041 credentials.token = "token"
Jon Wayne Parrott71ce2a02016-10-14 14:08:10 -070042
43 assert credentials.valid
44 assert not credentials.expired
45
Jon Wayne Parrott7af9f662017-05-08 09:40:56 -070046 # Set the expiration to one second more than now plus the clock skew
47 # accomodation. These credentials should be valid.
Jon Wayne Parrott71ce2a02016-10-14 14:08:10 -070048 credentials.expiry = (
Bu Sun Kim9eec0912019-10-21 17:04:21 -070049 datetime.datetime.utcnow() + _helpers.CLOCK_SKEW + datetime.timedelta(seconds=1)
50 )
Jon Wayne Parrotte60c1242017-03-23 16:00:24 -070051
52 assert credentials.valid
53 assert not credentials.expired
54
Jon Wayne Parrott7af9f662017-05-08 09:40:56 -070055 # Set the credentials expiration to now. Because of the clock skew
56 # accomodation, these credentials should report as expired.
57 credentials.expiry = datetime.datetime.utcnow()
Jon Wayne Parrott71ce2a02016-10-14 14:08:10 -070058
59 assert not credentials.valid
60 assert credentials.expired
61
62
63def test_before_request():
64 credentials = CredentialsImpl()
Bu Sun Kim9eec0912019-10-21 17:04:21 -070065 request = "token"
Jon Wayne Parrott71ce2a02016-10-14 14:08:10 -070066 headers = {}
67
68 # First call should call refresh, setting the token.
Bu Sun Kim9eec0912019-10-21 17:04:21 -070069 credentials.before_request(request, "http://example.com", "GET", headers)
Jon Wayne Parrott71ce2a02016-10-14 14:08:10 -070070 assert credentials.valid
Bu Sun Kim9eec0912019-10-21 17:04:21 -070071 assert credentials.token == "token"
72 assert headers["authorization"] == "Bearer token"
Jon Wayne Parrott71ce2a02016-10-14 14:08:10 -070073
Bu Sun Kim9eec0912019-10-21 17:04:21 -070074 request = "token2"
Jon Wayne Parrott71ce2a02016-10-14 14:08:10 -070075 headers = {}
76
77 # Second call shouldn't call refresh.
Bu Sun Kim9eec0912019-10-21 17:04:21 -070078 credentials.before_request(request, "http://example.com", "GET", headers)
Jon Wayne Parrott71ce2a02016-10-14 14:08:10 -070079 assert credentials.valid
Bu Sun Kim9eec0912019-10-21 17:04:21 -070080 assert credentials.token == "token"
81 assert headers["authorization"] == "Bearer token"
Jon Wayne Parrott71ce2a02016-10-14 14:08:10 -070082
83
Tres Seaverb096a3d2017-10-30 16:12:37 -040084def test_anonymous_credentials_ctor():
85 anon = credentials.AnonymousCredentials()
86 assert anon.token is None
87 assert anon.expiry is None
88 assert not anon.expired
89 assert anon.valid
90
91
92def test_anonymous_credentials_refresh():
93 anon = credentials.AnonymousCredentials()
94 request = object()
95 with pytest.raises(ValueError):
96 anon.refresh(request)
97
98
99def test_anonymous_credentials_apply_default():
100 anon = credentials.AnonymousCredentials()
101 headers = {}
102 anon.apply(headers)
103 assert headers == {}
104 with pytest.raises(ValueError):
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700105 anon.apply(headers, token="TOKEN")
Tres Seaverb096a3d2017-10-30 16:12:37 -0400106
107
108def test_anonymous_credentials_before_request():
109 anon = credentials.AnonymousCredentials()
110 request = object()
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700111 method = "GET"
112 url = "https://example.com/api/endpoint"
Tres Seaverb096a3d2017-10-30 16:12:37 -0400113 headers = {}
114 anon.before_request(request, method, url, headers)
115 assert headers == {}
116
117
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700118class ReadOnlyScopedCredentialsImpl(credentials.ReadOnlyScoped, CredentialsImpl):
Jon Wayne Parrott71ce2a02016-10-14 14:08:10 -0700119 @property
120 def requires_scopes(self):
Jon Wayne Parrott4460a962017-09-12 10:01:23 -0700121 return super(ReadOnlyScopedCredentialsImpl, self).requires_scopes
Jon Wayne Parrott71ce2a02016-10-14 14:08:10 -0700122
123
Tres Seaver42468322017-09-11 15:36:53 -0400124def test_readonly_scoped_credentials_constructor():
Jon Wayne Parrott4460a962017-09-12 10:01:23 -0700125 credentials = ReadOnlyScopedCredentialsImpl()
Jon Wayne Parrott71ce2a02016-10-14 14:08:10 -0700126 assert credentials._scopes is None
127
128
Tres Seaver42468322017-09-11 15:36:53 -0400129def test_readonly_scoped_credentials_scopes():
Jon Wayne Parrott4460a962017-09-12 10:01:23 -0700130 credentials = ReadOnlyScopedCredentialsImpl()
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700131 credentials._scopes = ["one", "two"]
132 assert credentials.scopes == ["one", "two"]
133 assert credentials.has_scopes(["one"])
134 assert credentials.has_scopes(["two"])
135 assert credentials.has_scopes(["one", "two"])
136 assert not credentials.has_scopes(["three"])
Jon Wayne Parrott71ce2a02016-10-14 14:08:10 -0700137
138
Tres Seaver42468322017-09-11 15:36:53 -0400139def test_readonly_scoped_credentials_requires_scopes():
Jon Wayne Parrott4460a962017-09-12 10:01:23 -0700140 credentials = ReadOnlyScopedCredentialsImpl()
Jon Wayne Parrott71ce2a02016-10-14 14:08:10 -0700141 assert not credentials.requires_scopes
Jon Wayne Parrottf89a3cf2016-10-31 10:52:57 -0700142
143
144class RequiresScopedCredentialsImpl(credentials.Scoped, CredentialsImpl):
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -0700145 def __init__(self, scopes=None, default_scopes=None):
Jon Wayne Parrottf89a3cf2016-10-31 10:52:57 -0700146 super(RequiresScopedCredentialsImpl, self).__init__()
147 self._scopes = scopes
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -0700148 self._default_scopes = default_scopes
Jon Wayne Parrottf89a3cf2016-10-31 10:52:57 -0700149
150 @property
151 def requires_scopes(self):
152 return not self.scopes
153
Bu Sun Kimbf5ce0c2021-02-01 15:17:49 -0700154 def with_scopes(self, scopes, default_scopes=None):
155 return RequiresScopedCredentialsImpl(
156 scopes=scopes, default_scopes=default_scopes
157 )
Jon Wayne Parrottf89a3cf2016-10-31 10:52:57 -0700158
159
160def test_create_scoped_if_required_scoped():
161 unscoped_credentials = RequiresScopedCredentialsImpl()
162 scoped_credentials = credentials.with_scopes_if_required(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700163 unscoped_credentials, ["one", "two"]
164 )
Jon Wayne Parrottf89a3cf2016-10-31 10:52:57 -0700165
166 assert scoped_credentials is not unscoped_credentials
167 assert not scoped_credentials.requires_scopes
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700168 assert scoped_credentials.has_scopes(["one", "two"])
Jon Wayne Parrottf89a3cf2016-10-31 10:52:57 -0700169
170
171def test_create_scoped_if_required_not_scopes():
172 unscoped_credentials = CredentialsImpl()
173 scoped_credentials = credentials.with_scopes_if_required(
Bu Sun Kim9eec0912019-10-21 17:04:21 -0700174 unscoped_credentials, ["one", "two"]
175 )
Jon Wayne Parrottf89a3cf2016-10-31 10:52:57 -0700176
177 assert scoped_credentials is unscoped_credentials