pass id_token on logout from FranceConnect (fixes #28997)

This commit is contained in:
Benjamin Dauvergne 2018-12-14 01:44:45 +01:00 committed by Thomas NOEL
parent b896d1af68
commit 43f0a85dd5
3 changed files with 16 additions and 9 deletions

View File

@ -168,9 +168,11 @@ def test_fc_login_page(caplog):
assert session.extra_user_variables['fc_sub'] == 'ymca'
resp = app.get('/logout')
assert resp.location.endswith('/ident/fc/logout')
resp = resp.follow()
assert resp.location == 'https://fcp.integ01.dev-franceconnect.fr/api/v1/logout?post_logout_redirect_uri=http%3A%2F%2Fexample.net'
splitted = urlparse.urlsplit(resp.location)
assert urlparse.urlunsplit((splitted.scheme, splitted.netloc, splitted.path, '', '')) \
== 'https://fcp.integ01.dev-franceconnect.fr/api/v1/logout'
assert urlparse.parse_qs(splitted.query)['post_logout_redirect_uri'] == ['http://example.net']
assert urlparse.parse_qs(splitted.query)['id_token_hint']
assert not get_session(app)
# Test error handling path

View File

@ -327,13 +327,14 @@ class FCAuthMethod(AuthMethod):
return None
# check id_token nonce
id_token = result['id_token']
access_token = result['access_token']
header, payload, signature = id_token.split('.')
payload = json_loads(base64url_decode(payload))
nonce = hashlib.sha256(str(session.id)).hexdigest()
if payload['nonce'] != nonce:
logger.error('FranceConnect returned nonce did not match')
return None
return result['access_token']
return access_token, id_token
def get_user_info(self, access_token):
logger = get_logger()
@ -436,7 +437,7 @@ class FCAuthMethod(AuthMethod):
logger.error(_('FranceConnect authentication failed: %s'),
_(msg) if msg else error)
return redirect(next_url)
access_token = self.get_access_token(request.form['code'])
access_token, id_token = self.get_access_token(request.form['code'])
if not access_token:
return redirect(next_url)
user_info = self.get_user_info(access_token)
@ -448,7 +449,8 @@ class FCAuthMethod(AuthMethod):
session_var_fc_user = {}
for key in flattened_user_info:
session_var_fc_user['fc_' + key] = flattened_user_info[key]
session_var_fc_user['fc_access_token'] = access_token
session_var_fc_user['fc_id_token'] = id_token
# Lookup or create user
sub = user_info['sub']
user = None
@ -471,9 +473,13 @@ class FCAuthMethod(AuthMethod):
return redirect(next_url)
def logout(self):
session = get_session()
id_token = session.extra_user_variables['fc_id_token']
get_session_manager().expire_session()
logout_url = self.get_logout_url()
post_logout_redirect_uri = get_publisher().get_frontoffice_url()
logout_url += '?' + urllib.urlencode({
'id_token_hint': id_token,
'post_logout_redirect_uri': post_logout_redirect_uri,
})
return redirect(logout_url)

View File

@ -265,9 +265,8 @@ class RootDirectory(Directory):
return redirect(get_publisher().get_root_url())
ident_methods = get_cfg('identification', {}).get('methods', [])
if 'fc' in ident_methods and session.extra_user_variables and 'fc_sub' in session.extra_user_variables:
get_session_manager().expire_session()
return redirect(get_publisher().get_root_url() + 'ident/fc/logout')
if 'fc' in ident_methods and session.extra_user_variables and 'fc_id_token' in session.extra_user_variables:
return get_publisher().ident_methods['fc']().logout()
if not 'idp' in ident_methods:
get_session_manager().expire_session()