From ace1421e58d4198941131c4092d56ce52c02e58b Mon Sep 17 00:00:00 2001 From: Benjamin Dauvergne Date: Mon, 9 Mar 2020 12:02:55 +0100 Subject: [PATCH] rest_authentication: raise APIError for signature errors (#39911) --- hobo/rest_authentication.py | 27 +++++++++++++-------- tests_authentic/test_rest_authentication.py | 2 +- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/hobo/rest_authentication.py b/hobo/rest_authentication.py index 485c1c0..175c442 100644 --- a/hobo/rest_authentication.py +++ b/hobo/rest_authentication.py @@ -1,6 +1,6 @@ import logging -from rest_framework import authentication, exceptions +from rest_framework import authentication, exceptions, status from hobo import signature @@ -61,6 +61,14 @@ class AnonymousAdminServiceUser(AnonymousUser): return 'Publik Service Admin' +class PublikAuthenticationFailed(exceptions.APIException): + status_code = status.HTTP_401_UNAUTHORIZED + default_code = 'invalid-signature' + + def __init__(self, code): + super(PublikAuthenticationFailed, self).__init__({'err': code}) + + class PublikAuthentication(authentication.BaseAuthentication): def __init__(self, *args, **kwargs): self.logger = logging.getLogger(__name__) @@ -80,16 +88,15 @@ class PublikAuthentication(authentication.BaseAuthentication): try: return User.objects.get(uuid=name_id) except User.DoesNotExist: - raise exceptions.AuthenticationFailed('No user matches uuid=%r' % name_id) + raise PublikAuthenticationFailed('user-not-found') + elif UserSAMLIdentifier: try: return UserSAMLIdentifier.objects.get(name_id=name_id).user except UserSAMLIdentifier.DoesNotExist: - raise exceptions.AuthenticationFailed( - 'No user matches nameid=%r' % name_id) + raise PublikAuthenticationFailed('user-not-found') else: - raise exceptions.AuthenticationFailed( - 'No usable model to match nameid=%r' % name_id) + raise PublikAuthenticationFailed('no-usable-model') else: orig = request.GET['orig'] try: @@ -100,18 +107,18 @@ class PublikAuthentication(authentication.BaseAuthentication): klass = import_string(settings.HOBO_ANONYMOUS_SERVICE_USER_CLASS) self.logger.info('anonymous signature validated') return klass() - raise exceptions.AuthenticationFailed('Anonymous service user is unsupported') + raise PublikAuthenticationFailed('no-user-for-orig') def get_orig_key(self, orig): if not hasattr(settings, 'KNOWN_SERVICES'): self.logger.warning('no known services') - raise exceptions.AuthenticationFailed('No KNOWN_SERVICES setting') + raise PublikAuthenticationFailed('no-known-services-setting') for service_id in settings.KNOWN_SERVICES: for slug, service in settings.KNOWN_SERVICES[service_id].items(): if service.get('verif_orig') == orig and service.get('secret'): return service['secret'] self.logger.warning('no secret found for origin %r', orig) - raise exceptions.AuthenticationFailed('no secret found for origin %r' % orig) + raise PublikAuthenticationFailed('no-secret-found-for-orig') def authenticate(self, request): full_path = request.get_full_path() @@ -120,7 +127,7 @@ class PublikAuthentication(authentication.BaseAuthentication): key = self.get_orig_key(request.GET['orig']) if not signature.check_url(full_path, key): self.logger.warning('invalid signature') - raise exceptions.AuthenticationFailed('Invalid signature') + raise PublikAuthenticationFailed('invalid-signature') user = self.resolve_user(request) self.logger.info('user authenticated with signature %s', user) return (user, None) diff --git a/tests_authentic/test_rest_authentication.py b/tests_authentic/test_rest_authentication.py index 349247d..74b2a8c 100644 --- a/tests_authentic/test_rest_authentication.py +++ b/tests_authentic/test_rest_authentication.py @@ -71,6 +71,6 @@ def test_publik_authentication(tenant, settings): request = factory.get(signature.sign_url(URL + AUTH_QUERY, key + 'zob')) publik_authentication = rest_authentication.PublikAuthentication() - with pytest.raises(AuthenticationFailed): + with pytest.raises(rest_authentication.PublikAuthenticationFailed): publik_authentication.authenticate(request) -- 2.24.0