21 |
21 |
has_providers)
|
22 |
22 |
from authentic2_auth_oidc.models import OIDCProvider, OIDCClaimMapping
|
23 |
23 |
from authentic2.models import AttributeValue
|
24 |
|
from authentic2.utils import timestamp_from_datetime
|
|
24 |
from authentic2.utils import timestamp_from_datetime, last_authentication_event
|
25 |
25 |
from authentic2.a2_rbac.utils import get_default_ou
|
26 |
26 |
from authentic2.crypto import base64url_encode
|
27 |
27 |
|
... | ... | |
166 |
166 |
|
167 |
167 |
|
168 |
168 |
def oidc_provider_mock(oidc_provider, oidc_provider_jwkset, code, extra_id_token=None,
|
169 |
|
extra_user_info=None, sub='john.doe'):
|
|
169 |
extra_user_info=None, sub='john.doe', nonce=None):
|
170 |
170 |
token_endpoint = urlparse.urlparse(oidc_provider.token_endpoint)
|
171 |
171 |
userinfo_endpoint = urlparse.urlparse(oidc_provider.userinfo_endpoint)
|
172 |
172 |
token_revocation_endpoint = urlparse.urlparse(oidc_provider.token_revocation_endpoint)
|
... | ... | |
181 |
181 |
'aud': str(oidc_provider.client_id),
|
182 |
182 |
'exp': timestamp_from_datetime(now() + datetime.timedelta(seconds=10)),
|
183 |
183 |
}
|
|
184 |
if nonce:
|
|
185 |
id_token['nonce'] = nonce
|
184 |
186 |
if extra_id_token:
|
185 |
187 |
id_token.update(extra_id_token)
|
186 |
188 |
|
... | ... | |
277 |
279 |
assert query['client_id'] == str(oidc_provider.client_id)
|
278 |
280 |
assert query['scope'] == 'openid'
|
279 |
281 |
assert query['redirect_uri'] == 'http://testserver' + reverse('oidc-login-callback')
|
|
282 |
# get the nonce
|
|
283 |
nonce = app.session['auth_oidc'][query['state']]['request']['nonce']
|
280 |
284 |
|
281 |
285 |
if oidc_provider.claims_parameter_supported:
|
282 |
286 |
claims = json.loads(query['claims'])
|
... | ... | |
312 |
316 |
with oidc_provider_mock(oidc_provider, oidc_provider_jwkset, code,
|
313 |
317 |
extra_id_token={'aud': 'zz'}):
|
314 |
318 |
response = app.get(login_callback_url, params={'code': code, 'state': query['state']})
|
|
319 |
with utils.check_log(caplog, 'expected nonce'):
|
|
320 |
with oidc_provider_mock(oidc_provider, oidc_provider_jwkset, code):
|
|
321 |
response = app.get(login_callback_url, params={'code': code, 'state': query['state']})
|
315 |
322 |
assert not hooks.auth_oidc_backend_modify_user
|
316 |
323 |
with utils.check_log(caplog, 'created user'):
|
317 |
|
with oidc_provider_mock(oidc_provider, oidc_provider_jwkset, code):
|
|
324 |
with oidc_provider_mock(oidc_provider, oidc_provider_jwkset, code, nonce=nonce):
|
318 |
325 |
response = app.get(login_callback_url, params={'code': code, 'state': query['state']})
|
319 |
326 |
assert len(hooks.auth_oidc_backend_modify_user) == 1
|
320 |
327 |
assert set(hooks.auth_oidc_backend_modify_user[0]['kwargs']) >= set(['user', 'provider', 'user_info', 'id_token', 'access_token'])
|
... | ... | |
330 |
337 |
assert user.attributes.last_name == 'Doe'
|
331 |
338 |
assert AttributeValue.objects.filter(content='John', verified=True).count() == 1
|
332 |
339 |
assert AttributeValue.objects.filter(content='Doe', verified=False).count() == 1
|
|
340 |
assert last_authentication_event(app.session)['nonce'] == nonce
|
333 |
341 |
|
334 |
342 |
with oidc_provider_mock(oidc_provider, oidc_provider_jwkset, code,
|
335 |
|
extra_user_info={'family_name_verified': True}):
|
|
343 |
extra_user_info={'family_name_verified': True}, nonce=nonce):
|
336 |
344 |
response = app.get(login_callback_url, params={'code': code, 'state': query['state']})
|
337 |
345 |
assert AttributeValue.objects.filter(content='Doe', verified=False).count() == 0
|
338 |
346 |
assert AttributeValue.objects.filter(content='Doe', verified=True).count() == 1
|
339 |
347 |
|
340 |
348 |
with oidc_provider_mock(oidc_provider, oidc_provider_jwkset, code,
|
341 |
|
extra_user_info={'ou': 'cassis'}):
|
|
349 |
extra_user_info={'ou': 'cassis'}, nonce=nonce):
|
342 |
350 |
response = app.get(login_callback_url, params={'code': code, 'state': query['state']})
|
343 |
351 |
assert User.objects.count() == 1
|
344 |
352 |
user = User.objects.get()
|
345 |
353 |
assert user.ou == cassis
|
346 |
354 |
|
347 |
|
with oidc_provider_mock(oidc_provider, oidc_provider_jwkset, code):
|
|
355 |
with oidc_provider_mock(oidc_provider, oidc_provider_jwkset, code, nonce=nonce):
|
348 |
356 |
response = app.get(login_callback_url, params={'code': code, 'state': query['state']})
|
349 |
357 |
assert User.objects.count() == 1
|
350 |
358 |
user = User.objects.get()
|
... | ... | |
403 |
411 |
response = response.click(oidc_provider.name)
|
404 |
412 |
location = urlparse.urlparse(response.location)
|
405 |
413 |
query = check_simple_qs(urlparse.parse_qs(location.query))
|
|
414 |
nonce = app.session['auth_oidc'][query['state']]['request']['nonce']
|
406 |
415 |
|
407 |
416 |
# sub=john.doe, MUST not work
|
408 |
417 |
with utils.check_log(caplog, 'cannot create user'):
|
409 |
|
with oidc_provider_mock(oidc_provider, oidc_provider_jwkset, code):
|
|
418 |
with oidc_provider_mock(oidc_provider, oidc_provider_jwkset, code, nonce=nonce):
|
410 |
419 |
response = app.get(login_callback_url, params={'code': code, 'state': query['state']})
|
411 |
420 |
|
412 |
421 |
# sub=simple_user.uuid MUST work
|
413 |
422 |
with utils.check_log(caplog, 'found user using UUID'):
|
414 |
|
with oidc_provider_mock(oidc_provider, oidc_provider_jwkset, code, sub=simple_user.uuid):
|
|
423 |
with oidc_provider_mock(oidc_provider, oidc_provider_jwkset, code, sub=simple_user.uuid, nonce=nonce):
|
415 |
424 |
response = app.get(login_callback_url, params={'code': code, 'state': query['state']})
|
416 |
425 |
|
417 |
426 |
assert urlparse.urlparse(response['Location']).path == '/'
|
... | ... | |
427 |
436 |
|
428 |
437 |
response = app.get(reverse('account_management'))
|
429 |
438 |
with utils.check_log(caplog, 'revoked token from OIDC'):
|
430 |
|
with oidc_provider_mock(oidc_provider, oidc_provider_jwkset, code):
|
|
439 |
with oidc_provider_mock(oidc_provider, oidc_provider_jwkset, code, nonce=nonce):
|
431 |
440 |
response = response.click(href='logout')
|
432 |
441 |
assert 'https://idp.example.com/logout' in response.content
|
433 |
|
-
|