11import json
2- import unittest
32import os
3+ import unittest
4+
45import requests
56
67from xcube .webapi .auth import AuthMixin
@@ -16,13 +17,17 @@ class RequestMock:
1617 def __init__ (self , headers ):
1718 self .headers = headers
1819
20+
1921XCUBE_TEST_CLIENT_ID = os .environ .get ('XCUBE_TEST_CLIENT_ID' )
2022XCUBE_TEST_CLIENT_SECRET = os .environ .get ('XCUBE_TEST_CLIENT_SECRET' )
2123
24+
2225class AuthMixinIdTokenTest (unittest .TestCase ):
2326
24- @unittest .skipUnless (XCUBE_TEST_CLIENT_ID and XCUBE_TEST_CLIENT_SECRET ,
25- 'XCUBE_TEST_CLIENT_ID and XCUBE_TEST_CLIENT_SECRET must be set' )
27+ @unittest .skipUnless (
28+ XCUBE_TEST_CLIENT_ID and XCUBE_TEST_CLIENT_SECRET ,
29+ 'XCUBE_TEST_CLIENT_ID and XCUBE_TEST_CLIENT_SECRET must be set'
30+ )
2631 def test_ok (self ):
2732 access_token = self ._fetch_access_token ()
2833
@@ -32,16 +37,28 @@ def test_ok(self):
3237 Domain = 'xcube-dev.eu.auth0.com' ,
3338 Audience = 'https://xcube-dev/api/'
3439 )))
35- auth_mixin .request = RequestMock (headers = {'Authorization' : f'Bearer { access_token } ' })
40+ auth_mixin .request = RequestMock (
41+ headers = {'Authorization' : f'Bearer { access_token } ' }
42+ )
3643
3744 id_token = auth_mixin .get_id_token ()
38- self .assertEqual ('https://xcube-dev.eu.auth0.com/' , id_token .get ('iss' ))
39- self .assertEqual ('https://xcube-dev/api/' , id_token .get ('aud' ))
40- self .assertEqual ('w2NoDEryIpNRtAQVH1ToU6XTurE549FW' , id_token .get ('azp' ))
41- self .assertEqual ('client-credentials' , id_token .get ('gty' ))
42- self .assertEqual ('w2NoDEryIpNRtAQVH1ToU6XTurE549FW@clients' , id_token .get ('sub' ))
43- self .assertEqual (['read:datasets' ], id_token .get ('permissions' ))
44- self .assertEqual (86400 , id_token .get ('exp' ) - id_token .get ('iat' ))
45+ self .assertEqual ('https://xcube-dev.eu.auth0.com/' ,
46+ id_token .get ('iss' ))
47+ self .assertEqual ('https://xcube-dev/api/' ,
48+ id_token .get ('aud' ))
49+ self .assertEqual ('w2NoDEryIpNRtAQVH1ToU6XTurE549FW' ,
50+ id_token .get ('azp' ))
51+ self .assertEqual ('client-credentials' ,
52+ id_token .get ('gty' ))
53+ self .assertEqual ('w2NoDEryIpNRtAQVH1ToU6XTurE549FW@clients' ,
54+ id_token .get ('sub' ))
55+ self .assertEqual (['read:datasets' ],
56+ id_token .get ('permissions' ))
57+ exp = id_token .get ('exp' )
58+ iat = id_token .get ('iat' )
59+ self .assertIsInstance (exp , int )
60+ self .assertIsInstance (iat , int )
61+ self .assertEqual (86400 , exp - iat )
4562
4663 def _fetch_access_token (self ):
4764 response = requests .post (
@@ -62,10 +79,11 @@ def _fetch_access_token(self):
6279
6380
6481 def test_missing_auth_config (self ):
65-
6682 auth_mixin = AuthMixin ()
6783 auth_mixin .service_context = ServiceContextMock (config = {})
68- auth_mixin .request = RequestMock (headers = {'Authorization' : f'Bearer my_t0k3n' })
84+ auth_mixin .request = RequestMock (
85+ headers = {'Authorization' : f'Bearer my_t0k3n' }
86+ )
6987
7088 with self .assertRaises (ServiceAuthError ) as cm :
7189 id_token = auth_mixin .get_id_token (require_auth = True )
@@ -79,8 +97,10 @@ def test_missing_access_token(self):
7997 auth_mixin .request = RequestMock (headers = {})
8098 self .assertEqual (None , auth_mixin .get_id_token ())
8199
82- @unittest .skipUnless (XCUBE_TEST_CLIENT_ID and XCUBE_TEST_CLIENT_SECRET ,
83- 'XCUBE_TEST_CLIENT_ID and XCUBE_TEST_CLIENT_SECRET must be set' )
100+ # @unittest.skipUnless(
101+ # XCUBE_TEST_CLIENT_ID and XCUBE_TEST_CLIENT_SECRET,
102+ # 'XCUBE_TEST_CLIENT_ID and XCUBE_TEST_CLIENT_SECRET must be set'
103+ # )
84104 def test_expired_access_token (self ):
85105 auth_mixin = AuthMixin ()
86106 auth_mixin .service_context = ServiceContextMock (config = dict (
@@ -89,26 +109,40 @@ def test_expired_access_token(self):
89109 Audience = 'https://xcube-dev/api/'
90110 )))
91111
92- expired_token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6Ik5VSkdSVUV5UWpNeE16UTVRVGMzTnpRM05URkNRa1ky" \
93- "TURGRE5qQkJSak5ETlRBeVFrWXdOUSJ9.eyJpc3MiOiJodHRwczovL3hjdWJlLWRldi5ldS5hdXRoMC5jb20vIiw" \
94- "ic3ViIjoidzJOb0RFcnlJcE5SdEFRVkgxVG9VNlhUdXJFNTQ5RldAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8veGN" \
95- "1YmUtZGV2L2FwaS8iLCJpYXQiOjE1Nzk0NTUxMDMsImV4cCI6MTU3OTU0MTUwMywiYXpwIjoidzJOb0RFcnlJcE5" \
96- "SdEFRVkgxVG9VNlhUdXJFNTQ5RlciLCJndHkiOiJjbGllbnQtY3JlZGVudGlhbHMiLCJwZXJtaXNzaW9ucyI6W11" \
97- "9.NtGuVp0yY8foR_eFiEmH0eXvCx85cvb5b1cPWCKs6LCNniUJJ3VnX5Fek08puW7Jidy-tj1UTzyG569dSHGDu3" \
98- "10Mf7xpQ9gyfZCWcaohERxsv9MrxHziqfGVnxv051rOB_c-fYyymrFnlsIqWeahcS7znvPoMovPO7E8MxVaIqxd_" \
99- "S4zKVlH025F-bDvytuwXD-rFmYVElCg7u2uOZKqjpF3lZCWc50_F1jSGcEQZv4daQJY-3lfU6TnEQAuGWlOVRrCN" \
100- "u05nlUBFPz6G82tB_nsP1uTa8uElOzoalVttXufLIeU0FL8Sv-lC6wUJTZAFpykLNmpA-vhkSeTqMv4g"
101- auth_mixin .request = RequestMock (headers = {'Authorization' : f'Bearer { expired_token } ' })
112+ expired_token = \
113+ "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCIsImtpZCI6" \
114+ "Ik5VSkdSVUV5UWpNeE16UTVRVGMzTnpRM05URkNRa1ky" \
115+ "TURGRE5qQkJSak5ETlRBeVFrWXdOUSJ9.eyJpc3MiOiJ" \
116+ "odHRwczovL3hjdWJlLWRldi5ldS5hdXRoMC5jb20vIiw" \
117+ "ic3ViIjoidzJOb0RFcnlJcE5SdEFRVkgxVG9VNlhUdXJ" \
118+ "FNTQ5RldAY2xpZW50cyIsImF1ZCI6Imh0dHBzOi8veGN" \
119+ "1YmUtZGV2L2FwaS8iLCJpYXQiOjE1Nzk0NTUxMDMsImV" \
120+ "4cCI6MTU3OTU0MTUwMywiYXpwIjoidzJOb0RFcnlJcE5" \
121+ "SdEFRVkgxVG9VNlhUdXJFNTQ5RlciLCJndHkiOiJjbGl" \
122+ "lbnQtY3JlZGVudGlhbHMiLCJwZXJtaXNzaW9ucyI6W11" \
123+ "9.NtGuVp0yY8foR_eFiEmH0eXvCx85cvb5b1cPWCKs6L" \
124+ "CNniUJJ3VnX5Fek08puW7Jidy-tj1UTzyG569dSHGDu3" \
125+ "10Mf7xpQ9gyfZCWcaohERxsv9MrxHziqfGVnxv051rOB" \
126+ "_c-fYyymrFnlsIqWeahcS7znvPoMovPO7E8MxVaIqxd_" \
127+ "S4zKVlH025F-bDvytuwXD-rFmYVElCg7u2uOZKqjpF3l" \
128+ "ZCWc50_F1jSGcEQZv4daQJY-3lfU6TnEQAuGWlOVRrCN" \
129+ "u05nlUBFPz6G82tB_nsP1uTa8uElOzoalVttXufLIeU0" \
130+ "FL8Sv-lC6wUJTZAFpykLNmpA-vhkSeTqMv4g"
131+ auth_mixin .request = RequestMock (
132+ headers = {'Authorization' : f'Bearer { expired_token } ' })
102133 with self .assertRaises (ServiceAuthError ) as cm :
103134 auth_mixin .get_id_token ()
104- self .assertEqual ('HTTP 401: Token expired (Token is expired)' , f'{ cm .exception } ' )
135+ self .assertEqual ('HTTP 401: Token expired (Token is expired)' ,
136+ f'{ cm .exception } ' )
105137
106138
107139class AuthMixinAccessTokenTest (unittest .TestCase ):
108140
109141 def test_ok (self ):
110142 auth_mixin = AuthMixin ()
111- auth_mixin .request = RequestMock (headers = {'Authorization' : 'Bearer my_t0k3n' })
143+ auth_mixin .request = RequestMock (
144+ headers = {'Authorization' : 'Bearer my_t0k3n' }
145+ )
112146 self .assertEqual ('my_t0k3n' , auth_mixin .get_access_token ())
113147
114148 def test_ok_no_auth (self ):
@@ -122,25 +156,34 @@ def test_not_ok(self):
122156 auth_mixin .request = RequestMock (headers = {})
123157 with self .assertRaises (ServiceAuthError ) as cm :
124158 auth_mixin .get_access_token (require_auth = True )
125- self .assertEqual ('HTTP 401: Authorization header missing (Authorization header is expected)' ,
159+ self .assertEqual ('HTTP 401: Authorization header'
160+ ' missing (Authorization header is expected)' ,
126161 f'{ cm .exception } ' )
127162
128- auth_mixin .request = RequestMock (headers = {'Authorization' : 'Beerer my_t0k3n' })
163+ auth_mixin .request = RequestMock (
164+ headers = {'Authorization' : 'Beerer my_t0k3n' }
165+ )
129166 with self .assertRaises (ServiceAuthError ) as cm :
130167 auth_mixin .get_access_token ()
131- self .assertEqual ('HTTP 401: Invalid header (Authorization header must start with "Bearer")' ,
168+ self .assertEqual ('HTTP 401: Invalid header'
169+ ' (Authorization header must start with "Bearer")' ,
132170 f'{ cm .exception } ' )
133171
134- auth_mixin .request = RequestMock (headers = {'Authorization' : 'Bearer' })
172+ auth_mixin .request = RequestMock (
173+ headers = {'Authorization' : 'Bearer' }
174+ )
135175 with self .assertRaises (ServiceAuthError ) as cm :
136176 auth_mixin .get_access_token ()
137177 self .assertEqual ('HTTP 401: Invalid header (Bearer token not found)' ,
138178 f'{ cm .exception } ' )
139179
140- auth_mixin .request = RequestMock (headers = {'Authorization' : 'Bearer my t0k3n' })
180+ auth_mixin .request = RequestMock (
181+ headers = {'Authorization' : 'Bearer my t0k3n' }
182+ )
141183 with self .assertRaises (ServiceAuthError ) as cm :
142184 auth_mixin .get_access_token ()
143- self .assertEqual ('HTTP 401: Invalid header (Authorization header must be Bearer token)' ,
185+ self .assertEqual ('HTTP 401: Invalid header'
186+ ' (Authorization header must be Bearer token)' ,
144187 f'{ cm .exception } ' )
145188
146189
@@ -154,16 +197,21 @@ def test_ok(self):
154197 Audience = 'https://xcube-dev/api/'
155198 )))
156199 auth_config = auth_mixin .auth_config
157- self .assertEqual ('xcube-dev.eu.auth0.com' , auth_config .domain )
158- self .assertEqual ('https://xcube-dev/api/' , auth_config .audience )
159- self .assertEqual ('https://xcube-dev.eu.auth0.com/' , auth_config .issuer )
160- self .assertEqual ('https://xcube-dev.eu.auth0.com/.well-known/jwks.json' , auth_config .well_known_jwks )
200+ self .assertEqual ('xcube-dev.eu.auth0.com' ,
201+ auth_config .domain )
202+ self .assertEqual ('https://xcube-dev/api/' ,
203+ auth_config .audience )
204+ self .assertEqual ('https://xcube-dev.eu.auth0.com/' ,
205+ auth_config .issuer )
206+ self .assertEqual ('https://xcube-dev.eu.auth0.com/'
207+ '.well-known/jwks.json' ,
208+ auth_config .well_known_jwks )
161209 self .assertEqual (['RS256' ], auth_config .algorithms )
162210
163211 def test_not_ok (self ):
164- class ServiceContextMock :
165- def __init__ (self , config ):
166- self .config = config
212+ # class ServiceContextMock:
213+ # def __init__(self, config):
214+ # self.config = config
167215
168216 auth_mixin = AuthMixin ()
169217 auth_mixin .service_context = ServiceContextMock (config = dict (
@@ -174,7 +222,8 @@ def __init__(self, config):
174222 with self .assertRaises (ServiceConfigError ) as cm :
175223 # noinspection PyUnusedLocal
176224 auth_config = auth_mixin .auth_config
177- self .assertEqual ('HTTP 500: Missing key "Audience" in section "Authentication"' ,
225+ self .assertEqual ('HTTP 500: Missing key'
226+ ' "Audience" in section "Authentication"' ,
178227 f'{ cm .exception } ' )
179228
180229 auth_mixin .service_context = ServiceContextMock (config = dict (
@@ -185,7 +234,8 @@ def __init__(self, config):
185234 with self .assertRaises (ServiceConfigError ) as cm :
186235 # noinspection PyUnusedLocal
187236 auth_config = auth_mixin .auth_config
188- self .assertEqual ('HTTP 500: Missing key "Domain" in section "Authentication"' ,
237+ self .assertEqual ('HTTP 500: Missing'
238+ ' key "Domain" in section "Authentication"' ,
189239 f'{ cm .exception } ' )
190240
191241 auth_mixin .service_context = ServiceContextMock (config = dict (
@@ -198,5 +248,6 @@ def __init__(self, config):
198248 with self .assertRaises (ServiceConfigError ) as cm :
199249 # noinspection PyUnusedLocal
200250 auth_config = auth_mixin .auth_config
201- self .assertEqual ('HTTP 500: Value for key "Algorithms" in section "Authentication" must not be empty' ,
251+ self .assertEqual ('HTTP 500: Value for key "Algorithms"'
252+ ' in section "Authentication" must not be empty' ,
202253 f'{ cm .exception } ' )
0 commit comments