diff --git a/apps/dot_ext/views/authorization.py b/apps/dot_ext/views/authorization.py index f0abc7e26..dd63ba8a4 100644 --- a/apps/dot_ext/views/authorization.py +++ b/apps/dot_ext/views/authorization.py @@ -20,6 +20,7 @@ IntrospectTokenView as DotIntrospectTokenView, ) from oauth2_provider.models import get_application_model +from oauthlib.oauth2 import AccessDeniedError from oauthlib.oauth2.rfc6749.errors import InvalidClientError, InvalidGrantError from urllib.parse import urlparse, parse_qs import html @@ -179,13 +180,19 @@ def form_valid(self, form): refresh_token_delete_cnt = 0 try: + if not scopes: + # Since the create_authorization_response will re-inject scopes even when none are + # valid, we want to pre-emptively treat this as an error case + raise OAuthToolkitError( + error=AccessDeniedError(state=credentials.get("state", None)), redirect_uri=credentials["redirect_uri"] + ) uri, headers, body, status = self.create_authorization_response( request=self.request, scopes=scopes, credentials=credentials, allow=allow ) except OAuthToolkitError as error: response = self.error_response(error, application) - if allow is False: + if allow is False or not scopes: (data_access_grant_delete_cnt, access_token_delete_cnt, refresh_token_delete_cnt) = remove_application_user_pair_tokens_data_access(application, self.request.user)