auth_oidc: report token endpoint errors to user and in logs (#47656)

This commit is contained in:
Benjamin Dauvergne 2021-04-09 15:52:35 +02:00
parent e7803635b9
commit cf9c0b2cc0
2 changed files with 55 additions and 3 deletions

View File

@ -207,6 +207,50 @@ class LoginCallback(View):
timeout=10,
)
response.raise_for_status()
except requests.HTTPError as e:
status_code = e.response.status_code
try:
content = response.json()
except ValueError:
content = response.content[:1024]
if isinstance(content, dict):
error = content.get('error')
error_description = content.get('error_description')
else:
error = None
error_description = None
logger.warning(
'auth_oidc: token_endpoint returned HTTP error status '
'%(status_code)s for %(issuer)s with content %(content)s'
% {
'issuer': provider.issuer,
'status_code': status_code,
'content': content,
}
)
if error:
messages.warning(
request,
_(
'Authentication on %(name)s failed with error "%(error)s", report %(request_id)s to an administrator. '
)
% {
'name': provider.name,
'error': error_description or error,
'request_id': request.request_id,
},
)
else:
messages.warning(
request,
_('Provider %(name)s is down, report %(request_id)s to ' 'an administrator. ')
% {
'name': provider.name,
'request_id': request.request_id,
},
)
return self.continue_to_next_url(request)
except requests.RequestException as e:
logger.warning(
'auth_oidc: failed to contact the token_endpoint for %(issuer)s, %(exception)s'

View File

@ -311,7 +311,12 @@ def oidc_provider_mock(
}
else:
return {
'content': json.dumps({'error': 'invalid request'}),
'content': json.dumps(
{
'error': 'invalid request',
'error_description': 'Requête invalide',
}
),
'headers': {
'content-type': 'application/json',
},
@ -481,9 +486,12 @@ def test_sso(app, caplog, code, oidc_provider, oidc_provider_jwkset, hooks):
assert User.objects.count() == 0
with utils.check_log(caplog, 'failed to contact the token_endpoint'):
with utils.check_log(caplog, "'error': 'invalid request'"):
with oidc_provider_mock(oidc_provider, oidc_provider_jwkset, code):
response = app.get(login_callback_url(oidc_provider), params={'code': 'yyyy', 'state': state})
response = app.get(
login_callback_url(oidc_provider), params={'code': 'yyyy', 'state': state}
).maybe_follow()
assert 'Requête invalide' in response
with utils.check_log(caplog, 'invalid id_token'):
with oidc_provider_mock(oidc_provider, oidc_provider_jwkset, code, extra_id_token={'iss': None}):
response = app.get(login_callback_url(oidc_provider), params={'code': code, 'state': state})