From 1541de6a6aef719100f9fc5f04e1c492a17b5dd1 Mon Sep 17 00:00:00 2001 From: Julien Barreau Date: Tue, 7 Nov 2023 10:28:35 +0100 Subject: [PATCH] fix(authentication_callback): return errors detail instead of generic error 500 (#148) --- django_forest/authentication/exception.py | 6 ++++++ django_forest/authentication/utils.py | 12 +++++++++++- django_forest/authentication/views/callback.py | 13 ++++++++++++- .../tests/authentication/views/test_callback.py | 16 ++++++++++++++++ 4 files changed, 45 insertions(+), 2 deletions(-) diff --git a/django_forest/authentication/exception.py b/django_forest/authentication/exception.py index 9c1fb269..28d47248 100644 --- a/django_forest/authentication/exception.py +++ b/django_forest/authentication/exception.py @@ -7,6 +7,12 @@ class BaseAuthenticationException(BaseForestException): class AuthenticationClientException(BaseAuthenticationException): STATUS = 401 +class AuthenticationOpenIdClientException(AuthenticationClientException): + def __init__(self, msg, error, error_description, state) -> None: + super().__init__(msg) + self.error = error + self.error_description = error_description + self.state = state class AuthenticationSettingsException(BaseAuthenticationException): STATUS = 500 diff --git a/django_forest/authentication/utils.py b/django_forest/authentication/utils.py index d225d063..8f1c1cca 100644 --- a/django_forest/authentication/utils.py +++ b/django_forest/authentication/utils.py @@ -1,11 +1,21 @@ from django.http import JsonResponse -from django_forest.authentication.exception import BaseAuthenticationException +from django_forest.authentication.exception import BaseAuthenticationException, AuthenticationOpenIdClientException def authentication_exception(f): def wrapper(*args, **kwargs): try: return f(*args, **kwargs) + except AuthenticationOpenIdClientException as error: + return JsonResponse( + { + "error": error.error, + "error_description": error.error_description, + "state": error.state + }, + status=error.STATUS + ) + except BaseAuthenticationException as error: return JsonResponse({'errors': [{'detail': str(error)}]}, status=error.STATUS) return wrapper diff --git a/django_forest/authentication/views/callback.py b/django_forest/authentication/views/callback.py index f9a2d353..bc4bdff6 100644 --- a/django_forest/authentication/views/callback.py +++ b/django_forest/authentication/views/callback.py @@ -7,7 +7,11 @@ from oic.oauth2 import AuthorizationResponse from django.http import JsonResponse from django.views.generic import View -from django_forest.authentication.exception import AuthenticationClientException, AuthenticationThirdPartyException +from django_forest.authentication.exception import ( + AuthenticationClientException, + AuthenticationOpenIdClientException, + AuthenticationThirdPartyException +) from django_forest.authentication.oidc.client_manager import OidcClientManager from django_forest.authentication.utils import authentication_exception @@ -63,6 +67,13 @@ def _handle_authent_error(self, response): ) def parse_authorization_response(self, client, state, full_path_info): + if "error" in self.request.GET: + raise AuthenticationOpenIdClientException( + "error given in the query GET params", + self.request.GET["error"], + self.request.GET["error_description"], + self.request.GET["state"] + ) return client.parse_response( AuthorizationResponse, info=full_path_info, diff --git a/django_forest/tests/authentication/views/test_callback.py b/django_forest/tests/authentication/views/test_callback.py index 274982dd..5c22d342 100644 --- a/django_forest/tests/authentication/views/test_callback.py +++ b/django_forest/tests/authentication/views/test_callback.py @@ -276,3 +276,19 @@ def test_iat_issued_in_future_outside_allowed_skew(self, mocked_requests_get, mo """ with self.assertRaises(IATError): self.client.get(self.url) + + + def test_trial_period_ended(self): + query={ + "error": "TrialBlockedError", + "error_description": "Your free trial has ended. We hope you enjoyed your experience with Forest Admin. " + "Upgrade now to continue accessing your project.", + "state": "{\"renderingId\": 36}", + } + url = reverse('django_forest:authentication:callback') + response = self.client.get(f'{url}?{urlencode(query)}') + self.assertEqual(response.status_code, 401) + body = response.json() + self.assertEqual(body["error"], query["error"]) + self.assertEqual(body["error_description"], query["error_description"]) + self.assertEqual(body["state"], query["state"]) \ No newline at end of file