diff options
author | Jonathan Huot <JonathanHuot@users.noreply.github.com> | 2018-12-20 15:47:01 +0100 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-20 15:47:01 +0100 |
commit | 650f5dbc750c5c07882b15bd99852c7a3000759e (patch) | |
tree | 74afb6e035f064ffe142bb97381936eb187dc77b | |
parent | cbb13792261b2df5c5ff408f9e73cdcb99aa94dd (diff) | |
parent | 3893b1764af522970e143f422967338eecbb9c1e (diff) | |
download | oauthlib-650f5dbc750c5c07882b15bd99852c7a3000759e.tar.gz |
Merge pull request #634 from oauthlib/dry-up-code
Extract common code into helpers
9 files changed, 104 insertions, 128 deletions
diff --git a/oauthlib/oauth2/rfc6749/endpoints/base.py b/oauthlib/oauth2/rfc6749/endpoints/base.py index cdb015f..c0fc726 100644 --- a/oauthlib/oauth2/rfc6749/endpoints/base.py +++ b/oauthlib/oauth2/rfc6749/endpoints/base.py @@ -12,7 +12,8 @@ import functools import logging from ..errors import (FatalClientError, OAuth2Error, ServerError, - TemporarilyUnavailableError) + TemporarilyUnavailableError, InvalidRequestError, + InvalidClientError, UnsupportedTokenTypeError) log = logging.getLogger(__name__) @@ -39,6 +40,28 @@ class BaseEndpoint(object): def catch_errors(self, catch_errors): self._catch_errors = catch_errors + def _raise_on_missing_token(self, request): + """Raise error on missing token.""" + if not request.token: + raise InvalidRequestError(request=request, + description='Missing token parameter.') + def _raise_on_invalid_client(self, request): + """Raise on failed client authentication.""" + if self.request_validator.client_authentication_required(request): + if not self.request_validator.authenticate_client(request): + log.debug('Client authentication failed, %r.', request) + raise InvalidClientError(request=request) + elif not self.request_validator.authenticate_client_id(request.client_id, request): + log.debug('Client authentication failed, %r.', request) + raise InvalidClientError(request=request) + + def _raise_on_unsupported_token(self, request): + """Raise on unsupported tokens.""" + if (request.token_type_hint and + request.token_type_hint in self.valid_token_types and + request.token_type_hint not in self.supported_token_types): + raise UnsupportedTokenTypeError(request=request) + def catch_errors_and_unavailability(f): @functools.wraps(f) diff --git a/oauthlib/oauth2/rfc6749/endpoints/introspect.py b/oauthlib/oauth2/rfc6749/endpoints/introspect.py index 4a531e4..ff7a32d 100644 --- a/oauthlib/oauth2/rfc6749/endpoints/introspect.py +++ b/oauthlib/oauth2/rfc6749/endpoints/introspect.py @@ -14,8 +14,7 @@ import logging from oauthlib.common import Request -from ..errors import (InvalidClientError, InvalidRequestError, OAuth2Error, - UnsupportedTokenTypeError) +from ..errors import OAuth2Error, UnsupportedTokenTypeError from .base import BaseEndpoint, catch_errors_and_unavailability log = logging.getLogger(__name__) @@ -118,19 +117,6 @@ class IntrospectEndpoint(BaseEndpoint): .. _`section 1.5`: http://tools.ietf.org/html/rfc6749#section-1.5 .. _`RFC6749`: http://tools.ietf.org/html/rfc6749 """ - if not request.token: - raise InvalidRequestError(request=request, - description='Missing token parameter.') - - if self.request_validator.client_authentication_required(request): - if not self.request_validator.authenticate_client(request): - log.debug('Client authentication failed, %r.', request) - raise InvalidClientError(request=request) - elif not self.request_validator.authenticate_client_id(request.client_id, request): - log.debug('Client authentication failed, %r.', request) - raise InvalidClientError(request=request) - - if (request.token_type_hint and - request.token_type_hint in self.valid_token_types and - request.token_type_hint not in self.supported_token_types): - raise UnsupportedTokenTypeError(request=request) + self._raise_on_missing_token(request) + self._raise_on_invalid_client(request) + self._raise_on_unsupported_token(request) diff --git a/oauthlib/oauth2/rfc6749/endpoints/revocation.py b/oauthlib/oauth2/rfc6749/endpoints/revocation.py index f7e591d..4cd96a7 100644 --- a/oauthlib/oauth2/rfc6749/endpoints/revocation.py +++ b/oauthlib/oauth2/rfc6749/endpoints/revocation.py @@ -13,8 +13,7 @@ import logging from oauthlib.common import Request -from ..errors import (InvalidClientError, InvalidRequestError, OAuth2Error, - UnsupportedTokenTypeError) +from ..errors import OAuth2Error, UnsupportedTokenTypeError from .base import BaseEndpoint, catch_errors_and_unavailability log = logging.getLogger(__name__) @@ -122,19 +121,6 @@ class RevocationEndpoint(BaseEndpoint): .. _`Section 4.1.2`: https://tools.ietf.org/html/draft-ietf-oauth-revocation-11#section-4.1.2 .. _`RFC6749`: https://tools.ietf.org/html/rfc6749 """ - if not request.token: - raise InvalidRequestError(request=request, - description='Missing token parameter.') - - if self.request_validator.client_authentication_required(request): - if not self.request_validator.authenticate_client(request): - log.debug('Client authentication failed, %r.', request) - raise InvalidClientError(request=request) - elif not self.request_validator.authenticate_client_id(request.client_id, request): - log.debug('Client authentication failed, %r.', request) - raise InvalidClientError(request=request) - - if (request.token_type_hint and - request.token_type_hint in self.valid_token_types and - request.token_type_hint not in self.supported_token_types): - raise UnsupportedTokenTypeError(request=request) + self._raise_on_missing_token(request) + self._raise_on_invalid_client(request) + self._raise_on_unsupported_token(request) diff --git a/oauthlib/oauth2/rfc6749/grant_types/authorization_code.py b/oauthlib/oauth2/rfc6749/grant_types/authorization_code.py index d56330a..6463391 100644 --- a/oauthlib/oauth2/rfc6749/grant_types/authorization_code.py +++ b/oauthlib/oauth2/rfc6749/grant_types/authorization_code.py @@ -11,7 +11,6 @@ import json import logging from oauthlib import common -from oauthlib.uri_validate import is_absolute_uri from .. import errors from .base import GrantTypeBase @@ -164,7 +163,7 @@ class AuthorizationCodeGrant(GrantTypeBase): def create_authorization_code(self, request): """ Generates an authorization grant represented as a dictionary. - + :param request: OAuthlib request. :type request: oauthlib.common.Request """ @@ -297,11 +296,7 @@ class AuthorizationCodeGrant(GrantTypeBase): oauthlib.oauth2.BearerToken. """ - headers = { - 'Content-Type': 'application/json', - 'Cache-Control': 'no-store', - 'Pragma': 'no-cache', - } + headers = self._get_default_headers() try: self.validate_token_request(request) log.debug('Token request validation ok for %r.', request) @@ -364,24 +359,10 @@ class AuthorizationCodeGrant(GrantTypeBase): # https://tools.ietf.org/html/rfc6749#section-3.1.2 log.debug('Validating redirection uri %s for client %s.', request.redirect_uri, request.client_id) - if request.redirect_uri is not None: - request.using_default_redirect_uri = False - log.debug('Using provided redirect_uri %s', request.redirect_uri) - if not is_absolute_uri(request.redirect_uri): - raise errors.InvalidRedirectURIError(request=request) - if not self.request_validator.validate_redirect_uri( - request.client_id, request.redirect_uri, request): - raise errors.MismatchingRedirectURIError(request=request) - else: - request.redirect_uri = self.request_validator.get_default_redirect_uri( - request.client_id, request) - request.using_default_redirect_uri = True - log.debug('Using default redirect_uri %s.', request.redirect_uri) - if not request.redirect_uri: - raise errors.MissingRedirectURIError(request=request) - if not is_absolute_uri(request.redirect_uri): - raise errors.InvalidRedirectURIError(request=request) + # OPTIONAL. As described in Section 3.1.2. + # https://tools.ietf.org/html/rfc6749#section-3.1.2 + self._handle_redirects(request) # Then check for normal errors. diff --git a/oauthlib/oauth2/rfc6749/grant_types/base.py b/oauthlib/oauth2/rfc6749/grant_types/base.py index 43f9db4..f0772e2 100644 --- a/oauthlib/oauth2/rfc6749/grant_types/base.py +++ b/oauthlib/oauth2/rfc6749/grant_types/base.py @@ -9,51 +9,53 @@ import logging from itertools import chain from oauthlib.common import add_params_to_uri +from oauthlib.uri_validate import is_absolute_uri from oauthlib.oauth2.rfc6749 import errors, utils from ..request_validator import RequestValidator log = logging.getLogger(__name__) + class ValidatorsContainer(object): """ - Container object for holding custom validator callables to be invoked - as part of the grant type `validate_authorization_request()` or - `validate_authorization_request()` methods on the various grant types. + Container object for holding custom validator callables to be invoked + as part of the grant type `validate_authorization_request()` or + `validate_authorization_request()` methods on the various grant types. - Authorization validators must be callables that take a request object and - return a dict, which may contain items to be added to the `request_info` - returned from the grant_type after validation. + Authorization validators must be callables that take a request object and + return a dict, which may contain items to be added to the `request_info` + returned from the grant_type after validation. - Token validators must be callables that take a request object and - return None. + Token validators must be callables that take a request object and + return None. - Both authorization validators and token validators may raise OAuth2 - exceptions if validation conditions fail. + Both authorization validators and token validators may raise OAuth2 + exceptions if validation conditions fail. - Authorization validators added to `pre_auth` will be run BEFORE - the standard validations (but after the critical ones that raise - fatal errors) as part of `validate_authorization_request()` + Authorization validators added to `pre_auth` will be run BEFORE + the standard validations (but after the critical ones that raise + fatal errors) as part of `validate_authorization_request()` - Authorization validators added to `post_auth` will be run AFTER - the standard validations as part of `validate_authorization_request()` + Authorization validators added to `post_auth` will be run AFTER + the standard validations as part of `validate_authorization_request()` - Token validators added to `pre_token` will be run BEFORE - the standard validations as part of `validate_token_request()` + Token validators added to `pre_token` will be run BEFORE + the standard validations as part of `validate_token_request()` - Token validators added to `post_token` will be run AFTER - the standard validations as part of `validate_token_request()` + Token validators added to `post_token` will be run AFTER + the standard validations as part of `validate_token_request()` - For example: + For example: - >>> def my_auth_validator(request): - ... return {'myval': True} - >>> auth_code_grant = AuthorizationCodeGrant(request_validator) - >>> auth_code_grant.custom_validators.pre_auth.append(my_auth_validator) - >>> def my_token_validator(request): - ... if not request.everything_okay: - ... raise errors.OAuth2Error("uh-oh") - >>> auth_code_grant.custom_validators.post_token.append(my_token_validator) + >>> def my_auth_validator(request): + ... return {'myval': True} + >>> auth_code_grant = AuthorizationCodeGrant(request_validator) + >>> auth_code_grant.custom_validators.pre_auth.append(my_auth_validator) + >>> def my_token_validator(request): + ... if not request.everything_okay: + ... raise errors.OAuth2Error("uh-oh") + >>> auth_code_grant.custom_validators.post_token.append(my_token_validator) """ def __init__(self, post_auth, post_token, @@ -216,3 +218,36 @@ class GrantTypeBase(object): raise NotImplementedError( 'Subclasses must set a valid default_response_mode') + + def _get_default_headers(self): + """Create default headers for grant responses.""" + return { + 'Content-Type': 'application/json', + 'Cache-Control': 'no-store', + 'Pragma': 'no-cache', + } + + def _handle_redirects(self, request): + if request.redirect_uri is not None: + request.using_default_redirect_uri = False + log.debug('Using provided redirect_uri %s', request.redirect_uri) + if not is_absolute_uri(request.redirect_uri): + raise errors.InvalidRedirectURIError(request=request) + + # The authorization server MUST verify that the redirection URI + # to which it will redirect the access token matches a + # redirection URI registered by the client as described in + # Section 3.1.2. + # https://tools.ietf.org/html/rfc6749#section-3.1.2 + if not self.request_validator.validate_redirect_uri( + request.client_id, request.redirect_uri, request): + raise errors.MismatchingRedirectURIError(request=request) + else: + request.redirect_uri = self.request_validator.get_default_redirect_uri( + request.client_id, request) + request.using_default_redirect_uri = True + log.debug('Using default redirect_uri %s.', request.redirect_uri) + if not request.redirect_uri: + raise errors.MissingRedirectURIError(request=request) + if not is_absolute_uri(request.redirect_uri): + raise errors.InvalidRedirectURIError(request=request) diff --git a/oauthlib/oauth2/rfc6749/grant_types/client_credentials.py b/oauthlib/oauth2/rfc6749/grant_types/client_credentials.py index 0e4f545..c966795 100644 --- a/oauthlib/oauth2/rfc6749/grant_types/client_credentials.py +++ b/oauthlib/oauth2/rfc6749/grant_types/client_credentials.py @@ -67,11 +67,7 @@ class ClientCredentialsGrant(GrantTypeBase): .. _`Section 5.1`: https://tools.ietf.org/html/rfc6749#section-5.1 .. _`Section 5.2`: https://tools.ietf.org/html/rfc6749#section-5.2 """ - headers = { - 'Content-Type': 'application/json', - 'Cache-Control': 'no-store', - 'Pragma': 'no-cache', - } + headers = self._get_default_headers() try: log.debug('Validating access token request, %r.', request) self.validate_token_request(request) diff --git a/oauthlib/oauth2/rfc6749/grant_types/implicit.py b/oauthlib/oauth2/rfc6749/grant_types/implicit.py index b29953b..d6de906 100644 --- a/oauthlib/oauth2/rfc6749/grant_types/implicit.py +++ b/oauthlib/oauth2/rfc6749/grant_types/implicit.py @@ -8,7 +8,6 @@ from __future__ import absolute_import, unicode_literals import logging from oauthlib import common -from oauthlib.uri_validate import is_absolute_uri from .. import errors from .base import GrantTypeBase @@ -307,29 +306,7 @@ class ImplicitGrant(GrantTypeBase): # OPTIONAL. As described in Section 3.1.2. # https://tools.ietf.org/html/rfc6749#section-3.1.2 - if request.redirect_uri is not None: - request.using_default_redirect_uri = False - log.debug('Using provided redirect_uri %s', request.redirect_uri) - if not is_absolute_uri(request.redirect_uri): - raise errors.InvalidRedirectURIError(request=request) - - # The authorization server MUST verify that the redirection URI - # to which it will redirect the access token matches a - # redirection URI registered by the client as described in - # Section 3.1.2. - # https://tools.ietf.org/html/rfc6749#section-3.1.2 - if not self.request_validator.validate_redirect_uri( - request.client_id, request.redirect_uri, request): - raise errors.MismatchingRedirectURIError(request=request) - else: - request.redirect_uri = self.request_validator.get_default_redirect_uri( - request.client_id, request) - request.using_default_redirect_uri = True - log.debug('Using default redirect_uri %s.', request.redirect_uri) - if not request.redirect_uri: - raise errors.MissingRedirectURIError(request=request) - if not is_absolute_uri(request.redirect_uri): - raise errors.InvalidRedirectURIError(request=request) + self._handle_redirects(request) # Then check for normal errors. diff --git a/oauthlib/oauth2/rfc6749/grant_types/refresh_token.py b/oauthlib/oauth2/rfc6749/grant_types/refresh_token.py index 67d65a7..bd519e8 100644 --- a/oauthlib/oauth2/rfc6749/grant_types/refresh_token.py +++ b/oauthlib/oauth2/rfc6749/grant_types/refresh_token.py @@ -54,11 +54,7 @@ class RefreshTokenGrant(GrantTypeBase): .. _`Section 5.1`: https://tools.ietf.org/html/rfc6749#section-5.1 .. _`Section 5.2`: https://tools.ietf.org/html/rfc6749#section-5.2 """ - headers = { - 'Content-Type': 'application/json', - 'Cache-Control': 'no-store', - 'Pragma': 'no-cache', - } + headers = self._get_default_headers() try: log.debug('Validating refresh token request, %r.', request) self.validate_token_request(request) diff --git a/oauthlib/oauth2/rfc6749/grant_types/resource_owner_password_credentials.py b/oauthlib/oauth2/rfc6749/grant_types/resource_owner_password_credentials.py index cb5a4ca..f765d91 100644 --- a/oauthlib/oauth2/rfc6749/grant_types/resource_owner_password_credentials.py +++ b/oauthlib/oauth2/rfc6749/grant_types/resource_owner_password_credentials.py @@ -87,11 +87,7 @@ class ResourceOwnerPasswordCredentialsGrant(GrantTypeBase): .. _`Section 5.1`: https://tools.ietf.org/html/rfc6749#section-5.1 .. _`Section 5.2`: https://tools.ietf.org/html/rfc6749#section-5.2 """ - headers = { - 'Content-Type': 'application/json', - 'Cache-Control': 'no-store', - 'Pragma': 'no-cache', - } + headers = self._get_default_headers() try: if self.request_validator.client_authentication_required(request): log.debug('Authenticating client, %r.', request) |