Skip to content

Commit

Permalink
Merge branch 'master' into fix/better-ipv6-for-uri-validator
Browse files Browse the repository at this point in the history
  • Loading branch information
pauldekkers committed May 10, 2021
2 parents cdca419 + 7c0b505 commit a212d22
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 56 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.rst
Expand Up @@ -20,6 +20,9 @@ OAuth2.0 Client - Bugfixes
constructor.
* #725: LegacyApplicationClient.prepare_request_body now correctly uses the default `scope` provided in constructor

OAuth2.0 Provider - Bugfixes
* #756: Different prompt values are now handled according to spec

3.1.0 (2019-08-06)
------------------
OAuth2.0 Provider - Features
Expand Down
1 change: 0 additions & 1 deletion oauthlib/openid/connect/core/grant_types/__init__.py
Expand Up @@ -8,6 +8,5 @@
AuthorizationCodeGrantDispatcher, AuthorizationTokenGrantDispatcher,
ImplicitTokenGrantDispatcher,
)
from .exceptions import OIDCNoPrompt
from .hybrid import HybridGrant
from .implicit import ImplicitGrant
9 changes: 1 addition & 8 deletions oauthlib/openid/connect/core/grant_types/base.py
Expand Up @@ -8,7 +8,6 @@
ConsentRequired, InvalidRequestError, LoginRequired,
)

from .exceptions import OIDCNoPrompt

log = logging.getLogger(__name__)

Expand All @@ -33,13 +32,7 @@ def validate_authorization_request(self, request):
: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
Expand Down
32 changes: 0 additions & 32 deletions oauthlib/openid/connect/core/grant_types/exceptions.py

This file was deleted.

50 changes: 44 additions & 6 deletions tests/openid/connect/core/grant_types/test_authorization_code.py
Expand Up @@ -3,11 +3,13 @@
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,
Expand Down Expand Up @@ -77,11 +79,7 @@ def test_authorization(self, generate_token):
@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)

Expand All @@ -92,28 +90,68 @@ def test_no_prompt_authorization(self, generate_token):
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)

# 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'
Expand Down
55 changes: 46 additions & 9 deletions tests/openid/connect/core/grant_types/test_implicit.py
Expand Up @@ -4,7 +4,6 @@
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
Expand Down Expand Up @@ -64,41 +63,79 @@ def test_authorization(self, generate_token):
@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'
Expand Down

0 comments on commit a212d22

Please sign in to comment.