From c7da8fc5c22b00f63ef6b7da9bf3bc17be8e2964 Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Fri, 9 Apr 2021 15:52:35 +0200 Subject: [PATCH] auth_oidc: report token endpoint errors to user and in logs (#47656) --- src/authentic2_auth_oidc/views.py | 44 +++++++++++++++++++++++++++++++ tests/test_auth_oidc.py | 14 +++++++--- 2 files changed, 55 insertions(+), 3 deletions(-) diff --git a/src/authentic2_auth_oidc/views.py b/src/authentic2_auth_oidc/views.py index 20f54950..b5d0c7c0 100644 --- a/src/authentic2_auth_oidc/views.py +++ b/src/authentic2_auth_oidc/views.py @@ -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' diff --git a/tests/test_auth_oidc.py b/tests/test_auth_oidc.py index a6c4ef02..9990671e 100644 --- a/tests/test_auth_oidc.py +++ b/tests/test_auth_oidc.py @@ -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}) -- 2.30.1