diff options
author | Wiliam Souza <wiliamsouza83@gmail.com> | 2018-06-05 11:33:21 -0300 |
---|---|---|
committer | Omer Katz <omer.drow@gmail.com> | 2018-06-05 17:33:21 +0300 |
commit | d5a4d5ea0eab04ddddefac7d1e7a4902fc469286 (patch) | |
tree | 580faf95f8f7bed257b2dac1d29c26c3d9d1b219 /oauthlib/oauth2/rfc6749/grant_types | |
parent | a102731c88f496b557dedd4024fb9b82801d134a (diff) | |
download | oauthlib-d5a4d5ea0eab04ddddefac7d1e7a4902fc469286.tar.gz |
OpenID Connect split (#525)
* Add command to clean up builds to makefile
* Fix docs strings for endpoints pre_configured
* Chnage grant_types.openid_connect to include a deprecation warning be a backward compatible
* Fix doc string for rfc6749.request_validator
* Remove unused import
* Change import to be explicity
* Move JWTTokenTestCase to openid.connect.core.test_token
* Move JWTToken to oauthlib.openid.connect.core.tokens
* Move to openid connect test
* Move openid connect exceptions to its own file
* Remove openid connect from oauth2 server
* Remove JWTToken from oauth tokens
* Remove grant_types.openid_connect file
* Add oauthlib/openid estructure and tests
Diffstat (limited to 'oauthlib/oauth2/rfc6749/grant_types')
-rw-r--r-- | oauthlib/oauth2/rfc6749/grant_types/__init__.py | 8 | ||||
-rw-r--r-- | oauthlib/oauth2/rfc6749/grant_types/openid_connect.py | 451 |
2 files changed, 0 insertions, 459 deletions
diff --git a/oauthlib/oauth2/rfc6749/grant_types/__init__.py b/oauthlib/oauth2/rfc6749/grant_types/__init__.py index 2e4bfe4..2ec8e4f 100644 --- a/oauthlib/oauth2/rfc6749/grant_types/__init__.py +++ b/oauthlib/oauth2/rfc6749/grant_types/__init__.py @@ -10,11 +10,3 @@ from .implicit import ImplicitGrant from .resource_owner_password_credentials import ResourceOwnerPasswordCredentialsGrant from .client_credentials import ClientCredentialsGrant from .refresh_token import RefreshTokenGrant -from .openid_connect import OpenIDConnectBase -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 -from .openid_connect import AuthTokenGrantDispatcher -from .openid_connect import ImplicitTokenGrantDispatcher diff --git a/oauthlib/oauth2/rfc6749/grant_types/openid_connect.py b/oauthlib/oauth2/rfc6749/grant_types/openid_connect.py deleted file mode 100644 index 4371b28..0000000 --- a/oauthlib/oauth2/rfc6749/grant_types/openid_connect.py +++ /dev/null @@ -1,451 +0,0 @@ -# -*- coding: utf-8 -*- -""" -oauthlib.oauth2.rfc6749.grant_types.openid_connect -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -""" -from __future__ import absolute_import, unicode_literals - -import datetime -import logging -from json import loads - -from ..errors import ConsentRequired, InvalidRequestError, LoginRequired -from ..request_validator import RequestValidator -from .authorization_code import AuthorizationCodeGrant -from .implicit import ImplicitGrant - -log = logging.getLogger(__name__) - - -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(OIDCNoPrompt, self).__init__(msg) - - -class AuthCodeGrantDispatcher(object): - """ - This is an adapter class that will route simple Authorization Code requests, those that have response_type=code and a scope - including 'openid' to either the default_auth_grant or the oidc_auth_grant based on the scopes requested. - """ - 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 request.scopes and "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 ImplicitTokenGrantDispatcher(object): - """ - This is an adapter class that will route simple Authorization Code requests, those that have response_type=code and a scope - including 'openid' to either the default_auth_grant or the oidc_auth_grant based on the scopes requested. - """ - def __init__(self, default_implicit_grant=None, oidc_implicit_grant=None): - self.default_implicit_grant = default_implicit_grant - self.oidc_implicit_grant = oidc_implicit_grant - - def _handler_for_request(self, request): - handler = self.default_implicit_grant - - if request.scopes and "openid" in request.scopes and 'id_token' in request.response_type: - handler = self.oidc_implicit_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 AuthTokenGrantDispatcher(object): - """ - This is an adapter class that will route simple Token requests, those that authorization_code have a scope - including 'openid' to either the default_token_grant or the oidc_token_grant based on the scopes requested. - """ - def __init__(self, request_validator, default_token_grant=None, oidc_token_grant=None): - self.default_token_grant = default_token_grant - self.oidc_token_grant = oidc_token_grant - self.request_validator = request_validator - - def _handler_for_request(self, request): - handler = self.default_token_grant - scopes = () - parameters = dict(request.decoded_body) - client_id = parameters.get('client_id', None) - code = parameters.get('code', None) - redirect_uri = parameters.get('redirect_uri', None) - - # If code is not pressent fallback to `default_token_grant` wich will - # raise an error for the missing `code` in `create_token_response` step. - if code: - scopes = self.request_validator.get_authorization_code_scopes(client_id, code, redirect_uri, request) - - if 'openid' in scopes: - handler = self.oidc_token_grant - - log.debug('Selecting handler for request %r.', handler) - return handler - - def create_token_response(self, request, token_handler): - handler = self._handler_for_request(request) - return handler.create_token_response(request, token_handler) - - -class OpenIDConnectBase(object): - - # Just proxy the majority of method calls through to the - # proxy_target grant type handler, which will usually be either - # the standard OAuth2 AuthCode or Implicit grant types. - def __getattr__(self, attr): - return getattr(self.proxy_target, attr) - - def __setattr__(self, attr, value): - proxied_attrs = set(('refresh_token', 'response_types')) - if attr in proxied_attrs: - setattr(self.proxy_target, attr, value) - else: - super(OpenIDConnectBase, self).__setattr__(attr, value) - - def validate_authorization_request(self, request): - """Validates the OpenID Connect authorization request parameters. - - :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) - - 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 request.scopes or 'openid' not in request.scopes: - return token - - # Only add an id token on auth/token step if asked for. - if request.response_type and 'id_token' not in request.response_type: - return token - - if 'state' not in token: - token['state'] = request.state - - if request.max_age: - d = datetime.datetime.utcnow() - token['auth_time'] = d.isoformat("T") + "Z" - - # TODO: acr claims (probably better handled by server code using oauthlib in get_id_token) - - token['id_token'] = self.request_validator.get_id_token(token, token_handler, request) - - return token - - def openid_authorization_validator(self, request): - """Perform OpenID Connect specific authorization request validation. - - nonce - OPTIONAL. String value used to associate a Client session with - an ID Token, and to mitigate replay attacks. The value is - passed through unmodified from the Authentication Request to - the ID Token. Sufficient entropy MUST be present in the nonce - values used to prevent attackers from guessing values - - display - OPTIONAL. ASCII string value that specifies how the - Authorization Server displays the authentication and consent - user interface pages to the End-User. The defined values are: - - page - The Authorization Server SHOULD display the - authentication and consent UI consistent with a full User - Agent page view. If the display parameter is not specified, - this is the default display mode. - - popup - The Authorization Server SHOULD display the - authentication and consent UI consistent with a popup User - Agent window. The popup User Agent window should be of an - appropriate size for a login-focused dialog and should not - obscure the entire window that it is popping up over. - - touch - The Authorization Server SHOULD display the - authentication and consent UI consistent with a device that - leverages a touch interface. - - wap - The Authorization Server SHOULD display the - authentication and consent UI consistent with a "feature - phone" type display. - - The Authorization Server MAY also attempt to detect the - capabilities of the User Agent and present an appropriate - display. - - prompt - OPTIONAL. Space delimited, case sensitive list of ASCII string - values that specifies whether the Authorization Server prompts - the End-User for reauthentication and consent. The defined - values are: - - none - The Authorization Server MUST NOT display any - authentication or consent user interface pages. An error is - returned if an End-User is not already authenticated or the - Client does not have pre-configured consent for the - requested Claims or does not fulfill other conditions for - processing the request. The error code will typically be - login_required, interaction_required, or another code - defined in Section 3.1.2.6. This can be used as a method to - check for existing authentication and/or consent. - - login - The Authorization Server SHOULD prompt the End-User - for reauthentication. If it cannot reauthenticate the - End-User, it MUST return an error, typically - login_required. - - consent - The Authorization Server SHOULD prompt the - End-User for consent before returning information to the - Client. If it cannot obtain consent, it MUST return an - error, typically consent_required. - - select_account - The Authorization Server SHOULD prompt the - End-User to select a user account. This enables an End-User - who has multiple accounts at the Authorization Server to - select amongst the multiple accounts that they might have - current sessions for. If it cannot obtain an account - selection choice made by the End-User, it MUST return an - error, typically account_selection_required. - - The prompt parameter can be used by the Client to make sure - that the End-User is still present for the current session or - to bring attention to the request. If this parameter contains - none with any other value, an error is returned. - - max_age - OPTIONAL. Maximum Authentication Age. Specifies the allowable - elapsed time in seconds since the last time the End-User was - actively authenticated by the OP. If the elapsed time is - greater than this value, the OP MUST attempt to actively - re-authenticate the End-User. (The max_age request parameter - corresponds to the OpenID 2.0 PAPE [OpenID.PAPE] max_auth_age - request parameter.) When max_age is used, the ID Token returned - MUST include an auth_time Claim Value. - - ui_locales - OPTIONAL. End-User's preferred languages and scripts for the - user interface, represented as a space-separated list of BCP47 - [RFC5646] language tag values, ordered by preference. For - instance, the value "fr-CA fr en" represents a preference for - French as spoken in Canada, then French (without a region - designation), followed by English (without a region - designation). An error SHOULD NOT result if some or all of the - requested locales are not supported by the OpenID Provider. - - id_token_hint - OPTIONAL. ID Token previously issued by the Authorization - Server being passed as a hint about the End-User's current or - past authenticated session with the Client. If the End-User - identified by the ID Token is logged in or is logged in by the - request, then the Authorization Server returns a positive - response; otherwise, it SHOULD return an error, such as - login_required. When possible, an id_token_hint SHOULD be - present when prompt=none is used and an invalid_request error - MAY be returned if it is not; however, the server SHOULD - respond successfully when possible, even if it is not present. - The Authorization Server need not be listed as an audience of - the ID Token when it is used as an id_token_hint value. If the - ID Token received by the RP from the OP is encrypted, to use it - as an id_token_hint, the Client MUST decrypt the signed ID - Token contained within the encrypted ID Token. The Client MAY - re-encrypt the signed ID token to the Authentication Server - using a key that enables the server to decrypt the ID Token, - and use the re-encrypted ID token as the id_token_hint value. - - login_hint - OPTIONAL. Hint to the Authorization Server about the login - identifier the End-User might use to log in (if necessary). - This hint can be used by an RP if it first asks the End-User - for their e-mail address (or other identifier) and then wants - to pass that value as a hint to the discovered authorization - service. It is RECOMMENDED that the hint value match the value - used for discovery. This value MAY also be a phone number in - the format specified for the phone_number Claim. The use of - this parameter is left to the OP's discretion. - - acr_values - OPTIONAL. Requested Authentication Context Class Reference - values. Space-separated string that specifies the acr values - that the Authorization Server is being requested to use for - processing this Authentication Request, with the values - appearing in order of preference. The Authentication Context - Class satisfied by the authentication performed is returned as - the acr Claim Value, as specified in Section 2. The acr Claim - is requested as a Voluntary Claim by this parameter. - """ - - # Treat it as normal OAuth 2 auth code request if openid is not present - if not request.scopes or 'openid' not in request.scopes: - return {} - - prompt = request.prompt if request.prompt else [] - if hasattr(prompt, 'split'): - prompt = prompt.strip().split() - prompt = set(prompt) - - if 'none' in prompt: - - if len(prompt) > 1: - msg = "Prompt none is mutually exclusive with other values." - raise InvalidRequestError(request=request, description=msg) - - # prompt other than 'none' should be handled by the server code that - # uses oauthlib - if not request.id_token_hint: - msg = "Prompt is set to none yet id_token_hint is missing." - raise InvalidRequestError(request=request, description=msg) - - if not self.request_validator.validate_silent_login(request): - raise LoginRequired(request=request) - - if not self.request_validator.validate_silent_authorization(request): - raise ConsentRequired(request=request) - - 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, - 'nonce': request.nonce, - 'prompt': prompt, - '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 - - def openid_implicit_authorization_validator(self, request): - """Additional validation when following the implicit flow. - """ - # Undefined in OpenID Connect, fall back to OAuth2 definition. - if request.response_type == 'token': - return {} - - # Treat it as normal OAuth 2 auth code request if openid is not present - if not request.scopes or 'openid' not in request.scopes: - return {} - - # REQUIRED. String value used to associate a Client session with an ID - # Token, and to mitigate replay attacks. The value is passed through - # unmodified from the Authentication Request to the ID Token. - # Sufficient entropy MUST be present in the nonce values used to - # prevent attackers from guessing values. For implementation notes, see - # Section 15.5.2. - if not request.nonce: - desc = 'Request is missing mandatory nonce parameter.' - raise InvalidRequestError(request=request, description=desc) - - return {} - - -class OpenIDConnectAuthCode(OpenIDConnectBase): - - def __init__(self, request_validator=None, **kwargs): - self.proxy_target = AuthorizationCodeGrant( - request_validator=request_validator, **kwargs) - self.custom_validators.post_auth.append( - self.openid_authorization_validator) - self.register_token_modifier(self.add_id_token) - - -class OpenIDConnectImplicit(OpenIDConnectBase): - - def __init__(self, request_validator=None, **kwargs): - self.proxy_target = ImplicitGrant( - request_validator=request_validator, **kwargs) - self.register_response_type('id_token') - self.register_response_type('id_token token') - self.custom_validators.post_auth.append( - self.openid_authorization_validator) - self.custom_validators.post_auth.append( - self.openid_implicit_authorization_validator) - self.register_token_modifier(self.add_id_token) - - -class OpenIDConnectHybrid(OpenIDConnectBase): - - def __init__(self, request_validator=None, **kwargs): - self.request_validator = request_validator or RequestValidator() - - self.proxy_target = AuthorizationCodeGrant( - request_validator=request_validator, **kwargs) - # All hybrid response types should be fragment-encoded. - self.proxy_target.default_response_mode = "fragment" - self.register_response_type('code id_token') - self.register_response_type('code token') - self.register_response_type('code id_token token') - self.custom_validators.post_auth.append( - self.openid_authorization_validator) - # Hybrid flows can return the id_token from the authorization - # endpoint as part of the 'code' response - self.register_code_modifier(self.add_token) - self.register_code_modifier(self.add_id_token) - self.register_token_modifier(self.add_id_token) |