summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorNikos Sklikas <nsklikas@admin.grnet.gr>2021-04-27 10:08:41 +0300
committerAsif Saif Uddin <auvipy@gmail.com>2021-05-01 14:12:17 +0600
commit2f1d7d8e357b307b3d5f41006d2b0a0698e40e63 (patch)
tree95d15b044f1bd156fbc2f15b25228d06bc542180
parentb69fa53fd836dc559aa7fcd78ce075bcbe361629 (diff)
downloadoauthlib-2f1d7d8e357b307b3d5f41006d2b0a0698e40e63.tar.gz
Properly handle prompt=none
-rw-r--r--oauthlib/openid/connect/core/grant_types/__init__.py1
-rw-r--r--oauthlib/openid/connect/core/grant_types/base.py9
-rw-r--r--oauthlib/openid/connect/core/grant_types/exceptions.py32
-rw-r--r--tests/openid/connect/core/grant_types/test_authorization_code.py50
-rw-r--r--tests/openid/connect/core/grant_types/test_implicit.py55
5 files changed, 91 insertions, 56 deletions
diff --git a/oauthlib/openid/connect/core/grant_types/__init__.py b/oauthlib/openid/connect/core/grant_types/__init__.py
index 768bb00..887a585 100644
--- a/oauthlib/openid/connect/core/grant_types/__init__.py
+++ b/oauthlib/openid/connect/core/grant_types/__init__.py
@@ -8,6 +8,5 @@ from .dispatchers import (
AuthorizationCodeGrantDispatcher, AuthorizationTokenGrantDispatcher,
ImplicitTokenGrantDispatcher,
)
-from .exceptions import OIDCNoPrompt
from .hybrid import HybridGrant
from .implicit import ImplicitGrant
diff --git a/oauthlib/openid/connect/core/grant_types/base.py b/oauthlib/openid/connect/core/grant_types/base.py
index d0a4812..76173e6 100644
--- a/oauthlib/openid/connect/core/grant_types/base.py
+++ b/oauthlib/openid/connect/core/grant_types/base.py
@@ -8,7 +8,6 @@ from oauthlib.oauth2.rfc6749.errors import (
ConsentRequired, InvalidRequestError, LoginRequired,
)
-from .exceptions import OIDCNoPrompt
log = logging.getLogger(__name__)
@@ -33,13 +32,7 @@ class GrantTypeBase:
:returns: (list of scopes, dict of request info)
"""
- # If request.prompt is 'none' then no login/authorization form should
- # be presented to the user. Instead, a silent login/authorization
- # should be performed.
- if request.prompt == 'none':
- raise OIDCNoPrompt()
- else:
- return self.proxy_target.validate_authorization_request(request)
+ return self.proxy_target.validate_authorization_request(request)
def _inflate_claims(self, request):
# this may be called multiple times in a single request so make sure we only de-serialize the claims once
diff --git a/oauthlib/openid/connect/core/grant_types/exceptions.py b/oauthlib/openid/connect/core/grant_types/exceptions.py
deleted file mode 100644
index 4636fe7..0000000
--- a/oauthlib/openid/connect/core/grant_types/exceptions.py
+++ /dev/null
@@ -1,32 +0,0 @@
-class OIDCNoPrompt(Exception):
- """Exception used to inform users that no explicit authorization is needed.
-
- Normally users authorize requests after validation of the request is done.
- Then post-authorization validation is again made and a response containing
- an auth code or token is created. However, when OIDC clients request
- no prompting of user authorization the final response is created directly.
-
- Example (without the shortcut for no prompt)
-
- scopes, req_info = endpoint.validate_authorization_request(url, ...)
- authorization_view = create_fancy_auth_form(scopes, req_info)
- return authorization_view
-
- Example (with the no prompt shortcut)
- try:
- scopes, req_info = endpoint.validate_authorization_request(url, ...)
- authorization_view = create_fancy_auth_form(scopes, req_info)
- return authorization_view
- except OIDCNoPrompt:
- # Note: Location will be set for you
- headers, body, status = endpoint.create_authorization_response(url, ...)
- redirect_view = create_redirect(headers, body, status)
- return redirect_view
- """
-
- def __init__(self):
- msg = ("OIDC request for no user interaction received. Do not ask user "
- "for authorization, it should been done using silent "
- "authentication through create_authorization_response. "
- "See OIDCNoPrompt.__doc__ for more details.")
- super().__init__(msg)
diff --git a/tests/openid/connect/core/grant_types/test_authorization_code.py b/tests/openid/connect/core/grant_types/test_authorization_code.py
index 91e24b3..f19b5fa 100644
--- a/tests/openid/connect/core/grant_types/test_authorization_code.py
+++ b/tests/openid/connect/core/grant_types/test_authorization_code.py
@@ -3,11 +3,13 @@ import json
from unittest import mock
from oauthlib.common import Request
+from oauthlib.oauth2.rfc6749.errors import (
+ ConsentRequired, InvalidRequestError, LoginRequired,
+)
from oauthlib.oauth2.rfc6749.tokens import BearerToken
from oauthlib.openid.connect.core.grant_types.authorization_code import (
AuthorizationCodeGrant,
)
-from oauthlib.openid.connect.core.grant_types.exceptions import OIDCNoPrompt
from tests.oauth2.rfc6749.grant_types.test_authorization_code import (
AuthorizationCodeGrantTest,
@@ -77,11 +79,7 @@ class OpenIDAuthCodeTest(TestCase):
@mock.patch('oauthlib.common.generate_token')
def test_no_prompt_authorization(self, generate_token):
generate_token.return_value = 'abc'
- scope, info = self.auth.validate_authorization_request(self.request)
self.request.prompt = 'none'
- self.assertRaises(OIDCNoPrompt,
- self.auth.validate_authorization_request,
- self.request)
bearer = BearerToken(self.mock_validator)
@@ -92,7 +90,7 @@ class OpenIDAuthCodeTest(TestCase):
self.assertIsNone(b)
self.assertEqual(s, 302)
- # Test alernative response modes
+ # Test alternative response modes
self.request.response_mode = 'fragment'
h, b, s = self.auth.create_authorization_response(self.request, bearer)
self.assertURLEqual(h['Location'], self.url_fragment, parse_fragment=True)
@@ -100,20 +98,60 @@ class OpenIDAuthCodeTest(TestCase):
# Ensure silent authentication and authorization is done
self.mock_validator.validate_silent_login.return_value = False
self.mock_validator.validate_silent_authorization.return_value = True
+ self.assertRaises(LoginRequired,
+ self.auth.validate_authorization_request,
+ self.request)
h, b, s = self.auth.create_authorization_response(self.request, bearer)
self.assertIn('error=login_required', h['Location'])
self.mock_validator.validate_silent_login.return_value = True
self.mock_validator.validate_silent_authorization.return_value = False
+ self.assertRaises(ConsentRequired,
+ self.auth.validate_authorization_request,
+ self.request)
h, b, s = self.auth.create_authorization_response(self.request, bearer)
self.assertIn('error=consent_required', h['Location'])
# ID token hint must match logged in user
self.mock_validator.validate_silent_authorization.return_value = True
self.mock_validator.validate_user_match.return_value = False
+ self.assertRaises(LoginRequired,
+ self.auth.validate_authorization_request,
+ self.request)
h, b, s = self.auth.create_authorization_response(self.request, bearer)
self.assertIn('error=login_required', h['Location'])
+ def test_none_multi_prompt(self):
+ bearer = BearerToken(self.mock_validator)
+
+ self.request.prompt = 'none login'
+ self.assertRaises(InvalidRequestError,
+ self.auth.validate_authorization_request,
+ self.request)
+ h, b, s = self.auth.create_authorization_response(self.request, bearer)
+ self.assertIn('error=invalid_request', h['Location'])
+
+ self.request.prompt = 'none consent'
+ self.assertRaises(InvalidRequestError,
+ self.auth.validate_authorization_request,
+ self.request)
+ h, b, s = self.auth.create_authorization_response(self.request, bearer)
+ self.assertIn('error=invalid_request', h['Location'])
+
+ self.request.prompt = 'none select_account'
+ self.assertRaises(InvalidRequestError,
+ self.auth.validate_authorization_request,
+ self.request)
+ h, b, s = self.auth.create_authorization_response(self.request, bearer)
+ self.assertIn('error=invalid_request', h['Location'])
+
+ self.request.prompt = 'consent none login'
+ self.assertRaises(InvalidRequestError,
+ self.auth.validate_authorization_request,
+ self.request)
+ h, b, s = self.auth.create_authorization_response(self.request, bearer)
+ self.assertIn('error=invalid_request', h['Location'])
+
def set_scopes(self, client_id, code, client, request):
request.scopes = self.request.scopes
request.user = 'bob'
diff --git a/tests/openid/connect/core/grant_types/test_implicit.py b/tests/openid/connect/core/grant_types/test_implicit.py
index 80069ac..6c22e90 100644
--- a/tests/openid/connect/core/grant_types/test_implicit.py
+++ b/tests/openid/connect/core/grant_types/test_implicit.py
@@ -4,7 +4,6 @@ from unittest import mock
from oauthlib.common import Request
from oauthlib.oauth2.rfc6749 import errors
from oauthlib.oauth2.rfc6749.tokens import BearerToken
-from oauthlib.openid.connect.core.grant_types.exceptions import OIDCNoPrompt
from oauthlib.openid.connect.core.grant_types.implicit import ImplicitGrant
from tests.oauth2.rfc6749.grant_types.test_implicit import ImplicitGrantTest
@@ -64,41 +63,79 @@ class OpenIDImplicitTest(TestCase):
@mock.patch('oauthlib.common.generate_token')
def test_no_prompt_authorization(self, generate_token):
generate_token.return_value = 'abc'
- scope, info = self.auth.validate_authorization_request(self.request)
self.request.prompt = 'none'
- self.assertRaises(OIDCNoPrompt,
- self.auth.validate_authorization_request,
- self.request)
bearer = BearerToken(self.mock_validator)
+
+ self.request.response_mode = 'query'
self.request.id_token_hint = 'me@email.com'
h, b, s = self.auth.create_authorization_response(self.request, bearer)
- self.assertURLEqual(h['Location'], self.url_fragment, parse_fragment=True)
+ self.assertURLEqual(h['Location'], self.url_query)
self.assertIsNone(b)
self.assertEqual(s, 302)
- # Test alernative response modes
- self.request.response_mode = 'query'
+ # Test alternative response modes
+ self.request.response_mode = 'fragment'
h, b, s = self.auth.create_authorization_response(self.request, bearer)
- self.assertURLEqual(h['Location'], self.url_query)
+ self.assertURLEqual(h['Location'], self.url_fragment, parse_fragment=True)
# Ensure silent authentication and authorization is done
self.mock_validator.validate_silent_login.return_value = False
self.mock_validator.validate_silent_authorization.return_value = True
+ self.assertRaises(errors.LoginRequired,
+ self.auth.validate_authorization_request,
+ self.request)
h, b, s = self.auth.create_authorization_response(self.request, bearer)
self.assertIn('error=login_required', h['Location'])
self.mock_validator.validate_silent_login.return_value = True
self.mock_validator.validate_silent_authorization.return_value = False
+ self.assertRaises(errors.ConsentRequired,
+ self.auth.validate_authorization_request,
+ self.request)
h, b, s = self.auth.create_authorization_response(self.request, bearer)
self.assertIn('error=consent_required', h['Location'])
# ID token hint must match logged in user
self.mock_validator.validate_silent_authorization.return_value = True
self.mock_validator.validate_user_match.return_value = False
+ self.assertRaises(errors.LoginRequired,
+ self.auth.validate_authorization_request,
+ self.request)
h, b, s = self.auth.create_authorization_response(self.request, bearer)
self.assertIn('error=login_required', h['Location'])
+ def test_none_multi_prompt(self):
+ bearer = BearerToken(self.mock_validator)
+
+ self.request.prompt = 'none login'
+ self.assertRaises(errors.InvalidRequestError,
+ self.auth.validate_authorization_request,
+ self.request)
+ h, b, s = self.auth.create_authorization_response(self.request, bearer)
+ self.assertIn('error=invalid_request', h['Location'])
+
+ self.request.prompt = 'none consent'
+ self.assertRaises(errors.InvalidRequestError,
+ self.auth.validate_authorization_request,
+ self.request)
+ h, b, s = self.auth.create_authorization_response(self.request, bearer)
+ self.assertIn('error=invalid_request', h['Location'])
+
+ self.request.prompt = 'none select_account'
+ self.assertRaises(errors.InvalidRequestError,
+ self.auth.validate_authorization_request,
+ self.request)
+ h, b, s = self.auth.create_authorization_response(self.request, bearer)
+ self.assertIn('error=invalid_request', h['Location'])
+
+ self.request.prompt = 'consent none login'
+ self.assertRaises(errors.InvalidRequestError,
+ self.auth.validate_authorization_request,
+ self.request)
+ h, b, s = self.auth.create_authorization_response(self.request, bearer)
+ self.assertIn('error=invalid_request', h['Location'])
+
@mock.patch('oauthlib.common.generate_token')
def test_required_nonce(self, generate_token):
generate_token.return_value = 'abc'