This repository has been archived on 2023-02-21. You can view files and clone it, but cannot push or open issues or pull requests.
authentic2-auth-fc/tests/test_auth_fc.py

101 lines
3.5 KiB
Python

import pytest
import urlparse
import httmock
import json
import base64
from jwcrypto import jwk, jwt
import datetime
from django.core.urlresolvers import reverse
from django.contrib.auth import get_user_model
from django.utils.timezone import now
from authentic2.utils import timestamp_from_datetime
User = get_user_model()
def hmac_jwt(payload, key):
header = {'alg': 'HS256'}
k = jwk.JWK(kty='oct', k=base64.b64encode(key.encode('utf-8')))
t = jwt.JWT(header=header, claims=payload)
t.make_signed_token(k)
return t.serialize()
def test_login_redirect(app, fc_settings):
url = reverse('fc-login-or-link')
response = app.get(url, status=302)
assert response['Location'].startswith('https://fcp.integ01')
def check_authorization_url(url):
callback = reverse('fc-login-or-link')
assert url.startswith('https://fcp.integ01')
query_string = url.split('?')[1]
parsed = {x: y[0] for x, y in urlparse.parse_qs(query_string).items()}
assert 'redirect_uri' in parsed
assert callback in parsed['redirect_uri']
assert 'client_id' in parsed
assert parsed['client_id'] == 'xxx'
assert 'scope' in parsed
assert set(parsed['scope'].split()) == set(['openid', 'profile', 'birth', 'email'])
assert 'state' in parsed
assert 'nonce' in parsed
assert parsed['state'] == parsed['nonce']
assert 'response_type' in parsed
assert parsed['response_type'] == 'code'
return parsed['state']
@pytest.mark.parametrize('exp', [timestamp_from_datetime(now() + datetime.timedelta(seconds=1000)),
timestamp_from_datetime(now() - datetime.timedelta(seconds=1000))])
def test_login(app, fc_settings, caplog, exp):
callback = reverse('fc-login-or-link')
response = app.get(callback, status=302)
location = response['Location']
state = check_authorization_url(location)
@httmock.urlmatch(path=r'.*/token$')
def access_token_response(url, request):
parsed = {x: y[0] for x, y in urlparse.parse_qs(request.body).items()}
assert set(parsed.keys()) == set(['code', 'client_id', 'client_secret', 'redirect_uri',
'grant_type'])
assert parsed['code'] == 'zzz'
assert parsed['client_id'] == 'xxx'
assert parsed['client_secret'] == 'yyy'
assert parsed['grant_type'] == 'authorization_code'
assert callback in parsed['redirect_uri']
id_token = {
'sub': '1234',
'aud': 'xxx',
'nonce': state,
'exp': exp,
'iss': 'https://fcp.integ01.dev-franceconnect.fr/',
}
return json.dumps({
'access_token': 'uuu',
'id_token': hmac_jwt(id_token, 'yyy')
})
@httmock.urlmatch(path=r'.*userinfo$')
def user_info_response(url, request):
assert request.headers['Authorization'] == 'Bearer uuu'
return json.dumps({
'sub': '1234',
'family_name': 'Doe',
'given_name': 'John',
})
with httmock.HTTMock(access_token_response, user_info_response):
response = app.get(callback + '?code=zzz&state=%s' % state, status=302)
assert User.objects.count() == 0
fc_settings.A2_FC_CREATE = True
with httmock.HTTMock(access_token_response, user_info_response):
response = app.get(callback + '?code=zzz&state=%s' % state, status=302)
if exp < timestamp_from_datetime(now()):
assert User.objects.count() == 0
else:
assert User.objects.count() == 1