apps: hide password management link when FC authenticated (#27083)
It's done by implementing a2_hook_user_can_change_password on the AppConfig object.
This commit is contained in:
parent
1f7b1c6a58
commit
ce56e15d0b
|
@ -1,6 +1,8 @@
|
|||
from . import utils
|
||||
from . import app_settings
|
||||
|
||||
from authentic2.utils import get_authentication_events
|
||||
|
||||
import django.apps
|
||||
|
||||
|
||||
|
@ -71,5 +73,11 @@ class AppConfig(django.apps.AppConfig):
|
|||
return True
|
||||
return None
|
||||
|
||||
def a2_hook_user_can_change_password(self, user, request, **kwargs):
|
||||
for authentication_event in get_authentication_events(request=request):
|
||||
if authentication_event['how'] == 'france-connect':
|
||||
return False
|
||||
return True
|
||||
|
||||
|
||||
default_app_config = '%s.%s' % (__name__, 'AppConfig')
|
||||
|
|
|
@ -456,3 +456,106 @@ def test_registration2(app, fc_settings, caplog, hooks):
|
|||
assert app.session['fc_states'][state]['next'] == '/accounts/'
|
||||
response = app.get(reverse('fc-logout') + '?state=' + state)
|
||||
assert path(response['Location']) == '/accounts/'
|
||||
|
||||
|
||||
def test_can_change_password(app, fc_settings, caplog, hooks):
|
||||
exp = timestamp_from_datetime(now() + datetime.timedelta(seconds=1000))
|
||||
response = app.get('/login/?service=portail&next=/idp/')
|
||||
response = response.click("Register")
|
||||
response = response.click(href='callback')
|
||||
# 1. Try a login
|
||||
# 2. Verify we come back to login page
|
||||
# 3. Check presence of registration link
|
||||
# 4. Follow it
|
||||
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/',
|
||||
'email': 'john.doe@example.com',
|
||||
}
|
||||
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': u'Frédérique',
|
||||
'given_name': u'Ÿuñe',
|
||||
'email': 'john.doe@example.com',
|
||||
})
|
||||
|
||||
callback = urlparse.parse_qs(urlparse.urlparse(location).query)['redirect_uri'][0]
|
||||
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
|
||||
assert path(response['Location']) == '/accounts/fc/register/'
|
||||
response = response.follow()
|
||||
location = response['Location']
|
||||
location.startswith('http://testserver/accounts/activate/')
|
||||
response = response.follow()
|
||||
assert hooks.calls['event'][0]['kwargs']['service'] == 'portail'
|
||||
assert hooks.calls['event'][1]['kwargs']['service'] == 'portail'
|
||||
# we must be connected
|
||||
assert app.session['_auth_user_id']
|
||||
# remove the registration parameter
|
||||
callback = callback.replace('®istration=', '')
|
||||
callback = callback.replace('?registration=', '?')
|
||||
callback = callback.replace('?&', '?')
|
||||
assert path_and_query(response['Location']) == path_and_query(callback)
|
||||
response = response.follow()
|
||||
location = response['Location']
|
||||
state = check_authorization_url(location)
|
||||
with httmock.HTTMock(access_token_response, user_info_response):
|
||||
response = app.get(callback + '&code=zzz&state=%s' % state, status=302)
|
||||
assert models.FcAccount.objects.count() == 1
|
||||
user = User.objects.get()
|
||||
assert user.verified_attributes.first_name == u'Ÿuñe'
|
||||
assert user.verified_attributes.last_name == u'Frédérique'
|
||||
response = app.get('/accounts/')
|
||||
assert len(response.pyquery('[href*="password/change"]')) == 0
|
||||
|
||||
# Login with password
|
||||
user = User.objects.get()
|
||||
user.set_password('test')
|
||||
user.save()
|
||||
app.session.flush()
|
||||
response = app.get('/login/')
|
||||
response.form.set('username', User.objects.get().email)
|
||||
response.form.set('password', 'test')
|
||||
response = response.form.submit(name='login-password-submit').follow()
|
||||
response = app.get('/accounts/')
|
||||
assert len(response.pyquery('[href*="password/change"]')) > 0
|
||||
|
||||
# Relogin with FC
|
||||
app.session.flush()
|
||||
response = app.get('/login/?service=portail&next=/accounts/')
|
||||
response = response.click(href='callback')
|
||||
location = response['Location']
|
||||
state = check_authorization_url(location)
|
||||
callback = urlparse.parse_qs(urlparse.urlparse(location).query)['redirect_uri'][0]
|
||||
with httmock.HTTMock(access_token_response, user_info_response):
|
||||
response = app.get(callback + '&code=zzz&state=%s' % state, status=302)
|
||||
# we must be connected
|
||||
assert app.session['_auth_user_id']
|
||||
assert path(response['Location']) == '/accounts/'
|
||||
response = response.follow()
|
||||
assert len(response.pyquery('[href*="password/change"]')) == 0
|
||||
|
|
Reference in New Issue