summaryrefslogtreecommitdiff
path: root/oauthlib/oauth2/rfc6749
diff options
context:
space:
mode:
authorJoel Stevenson <jstevenson@bepress.com>2016-08-18 15:29:01 -0700
committerJoel Stevenson <jstevenson@bepress.com>2016-08-18 15:29:01 -0700
commit447465547cc9a14350d024ed25b374614c475eec (patch)
treedb6a1aca50bb431f47412d7272c5aa6e627fcdd3 /oauthlib/oauth2/rfc6749
parent9a8f73d2dd088d5ea01313de2a1fe5a877994a79 (diff)
downloadoauthlib-447465547cc9a14350d024ed25b374614c475eec.tar.gz
Move the claims handling into OpenIDConnectBase._inflate_claims() and a new AuthCodeGrantDispatcher to route requests to either the default AuthorizationCodeGrant or OpenIDConnectAuthCode depending on scope when the request's response_type is a simple (ambiguous) 'code'.
Include basic docs about OpenID Connect auth flow support
Diffstat (limited to 'oauthlib/oauth2/rfc6749')
-rw-r--r--oauthlib/oauth2/rfc6749/endpoints/pre_configured.py5
-rw-r--r--oauthlib/oauth2/rfc6749/grant_types/__init__.py1
-rw-r--r--oauthlib/oauth2/rfc6749/grant_types/authorization_code.py15
-rw-r--r--oauthlib/oauth2/rfc6749/grant_types/openid_connect.py44
-rw-r--r--oauthlib/oauth2/rfc6749/request_validator.py12
5 files changed, 60 insertions, 17 deletions
diff --git a/oauthlib/oauth2/rfc6749/endpoints/pre_configured.py b/oauthlib/oauth2/rfc6749/endpoints/pre_configured.py
index 6ad5f5e..7463484 100644
--- a/oauthlib/oauth2/rfc6749/endpoints/pre_configured.py
+++ b/oauthlib/oauth2/rfc6749/endpoints/pre_configured.py
@@ -16,6 +16,7 @@ from ..grant_types import ResourceOwnerPasswordCredentialsGrant
from ..grant_types import ClientCredentialsGrant
from ..grant_types import RefreshTokenGrant
from ..grant_types import OpenIDConnectImplicit
+from ..grant_types import AuthCodeGrantDispatcher
from .authorization import AuthorizationEndpoint
from .token import TokenEndpoint
@@ -56,11 +57,13 @@ class Server(AuthorizationEndpoint, TokenEndpoint, ResourceEndpoint,
bearer = BearerToken(request_validator, token_generator,
token_expires_in, refresh_token_generator)
+ auth_grant_choice = AuthCodeGrantDispatcher( default_auth_grant=auth_grant, oidc_auth_grant=openid_connect_auth)
+
# See http://openid.net/specs/oauth-v2-multiple-response-types-1_0.html#Combinations for valid combinations
# internally our AuthorizationEndpoint will ensure they can appear in any order for any valid combination
AuthorizationEndpoint.__init__(self, default_response_type='code',
response_types={
- 'code': auth_grant,
+ 'code': auth_grant_choice,
'token': implicit_grant,
'id_token': openid_connect_implicit,
'id_token token': openid_connect_implicit,
diff --git a/oauthlib/oauth2/rfc6749/grant_types/__init__.py b/oauthlib/oauth2/rfc6749/grant_types/__init__.py
index 78cd7ed..1da1281 100644
--- a/oauthlib/oauth2/rfc6749/grant_types/__init__.py
+++ b/oauthlib/oauth2/rfc6749/grant_types/__init__.py
@@ -15,3 +15,4 @@ from .openid_connect import OpenIDConnectAuthCode
from .openid_connect import OpenIDConnectImplicit
from .openid_connect import OpenIDConnectHybrid
from .openid_connect import OIDCNoPrompt
+from .openid_connect import AuthCodeGrantDispatcher
diff --git a/oauthlib/oauth2/rfc6749/grant_types/authorization_code.py b/oauthlib/oauth2/rfc6749/grant_types/authorization_code.py
index 3a77fd9..d4292cb 100644
--- a/oauthlib/oauth2/rfc6749/grant_types/authorization_code.py
+++ b/oauthlib/oauth2/rfc6749/grant_types/authorization_code.py
@@ -367,25 +367,12 @@ class AuthorizationCodeGrant(GrantTypeBase):
# http://tools.ietf.org/html/rfc6749#section-3.3
self.validate_scopes(request)
- # validate_authorization_request may be called multiple times in a single request
- # so make sure we only de-serialize the claims once
- if request.claims and not isinstance(request.claims, dict) and request.scopes and "openid" in request.scopes:
- # specific claims are requested during the Authorization Request and may be requested for inclusion
- # in either the id_token or the UserInfo endpoint response
- # see http://openid.net/specs/openid-connect-core-1_0.html#ClaimsParameter
- try:
- request.claims = json.loads(request.claims)
- except Exception as ex:
- raise errors.InvalidRequestError(description="Malformed claims parameter",
- uri="http://openid.net/specs/openid-connect-core-1_0.html#ClaimsParameter")
-
request_info = {
'client_id': request.client_id,
'redirect_uri': request.redirect_uri,
'response_type': request.response_type,
'state': request.state,
- 'request': request,
- 'claims': request.claims
+ 'request': request
}
for validator in self._authorization_validators:
diff --git a/oauthlib/oauth2/rfc6749/grant_types/openid_connect.py b/oauthlib/oauth2/rfc6749/grant_types/openid_connect.py
index f9b38ba..3c3deb2 100644
--- a/oauthlib/oauth2/rfc6749/grant_types/openid_connect.py
+++ b/oauthlib/oauth2/rfc6749/grant_types/openid_connect.py
@@ -52,11 +52,47 @@ class OIDCNoPrompt(Exception):
super(OIDCNoPrompt, self).__init__(msg)
+class AuthCodeGrantDispatcher(object):
+ """
+
+ """
+ def __init__(self, default_auth_grant=None, oidc_auth_grant=None):
+ self.default_auth_grant = default_auth_grant
+ self.oidc_auth_grant = oidc_auth_grant
+
+ def _handler_for_request(self, request):
+ handler = self.default_auth_grant
+
+ if "openid" in request.scopes:
+ handler = self.oidc_auth_grant
+
+ log.debug('Selecting handler for request %r.', handler)
+ return handler
+
+ def create_authorization_response(self, request, token_handler):
+ return self._handler_for_request(request).create_authorization_response(request, token_handler)
+
+ def validate_authorization_request(self, request):
+ return self._handler_for_request(request).validate_authorization_request(request)
+
+
class OpenIDConnectBase(GrantTypeBase):
def __init__(self, request_validator=None):
self.request_validator = request_validator or RequestValidator()
+ 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
+ if request.claims and not isinstance(request.claims, dict):
+ # specific claims are requested during the Authorization Request and may be requested for inclusion
+ # in either the id_token or the UserInfo endpoint response
+ # see http://openid.net/specs/openid-connect-core-1_0.html#ClaimsParameter
+ try:
+ request.claims = loads(request.claims)
+ except Exception as ex:
+ raise InvalidRequestError(description="Malformed claims parameter",
+ uri="http://openid.net/specs/openid-connect-core-1_0.html#ClaimsParameter")
+
def add_id_token(self, token, token_handler, request):
# Treat it as normal OAuth 2 auth code request if openid is not present
if not 'openid' in request.scopes:
@@ -226,19 +262,21 @@ class OpenIDConnectBase(GrantTypeBase):
if not self.request_validator.validate_silent_authorization(request):
raise ConsentRequired(request=request)
- request.claims = loads(request.claims) if request.claims else {}
+ self._inflate_claims(request)
if not self.request_validator.validate_user_match(
request.id_token_hint, request.scopes, request.claims, request):
msg = "Session user does not match client supplied user."
raise LoginRequired(request=request, description=msg)
+
request_info = {
'display': request.display,
'prompt': request.prompt.split() if request.prompt else [],
'ui_locales': request.ui_locales.split() if request.ui_locales else [],
'id_token_hint': request.id_token_hint,
'login_hint': request.login_hint,
+ 'claims': request.claims
}
return request_info
@@ -263,7 +301,9 @@ class OpenIDConnectBase(GrantTypeBase):
desc = 'Request is missing mandatory nonce parameter.'
raise InvalidRequestError(request=request, description=desc)
- return {'nonce': request.nonce}
+ self._inflate_claims(request)
+
+ return {'nonce': request.nonce, 'claims': request.claims}
class OpenIDConnectAuthCode(OpenIDConnectBase):
diff --git a/oauthlib/oauth2/rfc6749/request_validator.py b/oauthlib/oauth2/rfc6749/request_validator.py
index b1c1bd1..2acd8ec 100644
--- a/oauthlib/oauth2/rfc6749/request_validator.py
+++ b/oauthlib/oauth2/rfc6749/request_validator.py
@@ -300,6 +300,18 @@ class RequestValidator(object):
- nonce, if workflow is implicit or hybrid and it was provided
- claims, if provided to the original Authorization Code request
+ The token parameter is a dict which may contain an ``access_token`` entry, in which
+ case the resulting ID Token *should* include a calculated ``at_hash`` claim.
+
+ Similarly, when the request parameter has a ``code`` property defined, the ID Token
+ *should* include a calculated ``c_hash`` claim.
+
+ http://openid.net/specs/openid-connect-core-1_0.html (sections `3.1.3.6`_, `3.2.2.10`_, `3.3.2.11`_)
+
+ .. _`3.1.3.6`: http://openid.net/specs/openid-connect-core-1_0.html#CodeIDToken
+ .. _`3.2.2.10`: http://openid.net/specs/openid-connect-core-1_0.html#ImplicitIDToken
+ .. _`3.3.2.11`: http://openid.net/specs/openid-connect-core-1_0.html#HybridIDToken
+
:param token: A Bearer token dict
:param token_handler: the token handler (BearerToken class)
:param request: the HTTP Request (oauthlib.common.Request)