Skip to content

Commit

Permalink
Add prompt=none support (#1268)
Browse files Browse the repository at this point in the history
  • Loading branch information
andyzickler committed Nov 10, 2023
1 parent 5d5246a commit 29a0472
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 0 deletions.
1 change: 1 addition & 0 deletions AUTHORS
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ Allisson Azevedo
Andrea Greco
Andrej Zbín
Andrew Chen Wang
Andrew Zickler
Antoine Laurent
Anvesh Agarwal
Aristóbulo Meneses
Expand Down
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* #1311 Add option to disable client_secret hashing to allow verifying JWTs' signatures.
* #1337 Gracefully handle expired or deleted refresh tokens, in `validate_user`.
* #1350 Support Python 3.12 and Django 5.0
* #1268 Support prompt=none in authentication request for Silent Authentication

### Fixed
* #1322 Instructions in documentation on how to create a code challenge and code verifier
Expand Down
27 changes: 27 additions & 0 deletions oauth2_provider/views/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,33 @@ def handle_prompt_login(self):
self.get_redirect_field_name(),
)

def handle_no_permission(self):
"""
Generate response for unauthorized users.
If prompt is set to none, then we redirect with an error code
as defined by OIDC 3.1.2.6
Some code copied from OAuthLibMixin.error_response, but that is designed
to operated on OAuth1Error from oauthlib wrapped in a OAuthToolkitError
"""
prompt = self.request.GET.get("prompt")
redirect_uri = self.request.GET.get("redirect_uri")
if prompt == "none" and redirect_uri:
response_parameters = {"error": "login_required"}

# REQUIRED if the Authorization Request included the state parameter.
# Set to the value received from the Client
state = self.request.GET.get("state")
if state:
response_parameters["state"] = state

separator = "&" if "?" in redirect_uri else "?"
redirect_to = redirect_uri + separator + urlencode(response_parameters)
return self.redirect(redirect_to, application=None)
else:
super().handle_no_permission()


@method_decorator(csrf_exempt, name="dispatch")
class TokenView(OAuthLibMixin, View):
Expand Down
27 changes: 27 additions & 0 deletions tests/test_authorization_code.py
Original file line number Diff line number Diff line change
Expand Up @@ -645,6 +645,33 @@ def test_prompt_login(self):

self.assertNotIn("prompt=login", next)

def test_prompt_none_unauthorized(self):
"""
Test response for redirect when supplied with prompt: none
Should redirect to redirect_uri with an error of login_required
"""
self.oauth2_settings.PKCE_REQUIRED = False

query_data = {
"client_id": self.application.client_id,
"response_type": "code",
"state": "random_state_string",
"scope": "read write",
"redirect_uri": "http://example.org",
"prompt": "none",
}

response = self.client.get(reverse("oauth2_provider:authorize"), data=query_data)

self.assertEqual(response.status_code, 302)

scheme, netloc, path, params, query, fragment = urlparse(response["Location"])
parsed_query = parse_qs(query)

self.assertIn("login_required", parsed_query["error"])
self.assertIn("random_state_string", parsed_query["state"])


class BaseAuthorizationCodeTokenView(BaseTest):
def get_auth(self, scope="read write"):
Expand Down

0 comments on commit 29a0472

Please sign in to comment.