diff options
author | Omer Katz <omer.drow@gmail.com> | 2019-06-29 10:46:10 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-29 10:46:10 +0300 |
commit | 9bcf5d6720aea23dd8b57e08dca39341dc49314a (patch) | |
tree | 2ce81e3c4e7c22e6ab04f2651814a3c641d44f74 /oauthlib/oauth2/rfc6749 | |
parent | 73092d039fa67a88d0989e7bf0ae7d0044a0bdc6 (diff) | |
parent | 76d8d3426004e3a14d372444c56f764ad71937e0 (diff) | |
download | oauthlib-9bcf5d6720aea23dd8b57e08dca39341dc49314a.tar.gz |
Merge branch 'master' into 672-fix-null-expires-in
Diffstat (limited to 'oauthlib/oauth2/rfc6749')
-rw-r--r-- | oauthlib/oauth2/rfc6749/endpoints/base.py | 31 | ||||
-rw-r--r-- | oauthlib/oauth2/rfc6749/endpoints/introspect.py | 3 | ||||
-rw-r--r-- | oauthlib/oauth2/rfc6749/endpoints/revocation.py | 3 | ||||
-rw-r--r-- | oauthlib/oauth2/rfc6749/endpoints/token.py | 10 | ||||
-rw-r--r-- | oauthlib/oauth2/rfc6749/grant_types/authorization_code.py | 3 | ||||
-rw-r--r-- | oauthlib/oauth2/rfc6749/parameters.py | 9 | ||||
-rw-r--r-- | oauthlib/oauth2/rfc6749/request_validator.py | 3 | ||||
-rw-r--r-- | oauthlib/oauth2/rfc6749/tokens.py | 4 |
8 files changed, 58 insertions, 8 deletions
diff --git a/oauthlib/oauth2/rfc6749/endpoints/base.py b/oauthlib/oauth2/rfc6749/endpoints/base.py index c0fc726..e39232f 100644 --- a/oauthlib/oauth2/rfc6749/endpoints/base.py +++ b/oauthlib/oauth2/rfc6749/endpoints/base.py @@ -15,6 +15,8 @@ from ..errors import (FatalClientError, OAuth2Error, ServerError, TemporarilyUnavailableError, InvalidRequestError, InvalidClientError, UnsupportedTokenTypeError) +from oauthlib.common import CaseInsensitiveDict, urldecode + log = logging.getLogger(__name__) @@ -23,6 +25,18 @@ class BaseEndpoint(object): def __init__(self): self._available = True self._catch_errors = False + self._valid_request_methods = None + + @property + def valid_request_methods(self): + return self._valid_request_methods + + @valid_request_methods.setter + def valid_request_methods(self, valid_request_methods): + if valid_request_methods is not None: + valid_request_methods = [x.upper() for x in valid_request_methods] + self._valid_request_methods = valid_request_methods + @property def available(self): @@ -30,7 +44,7 @@ class BaseEndpoint(object): @available.setter def available(self, available): - self._available = available + self._available = available @property def catch_errors(self): @@ -62,6 +76,21 @@ class BaseEndpoint(object): request.token_type_hint not in self.supported_token_types): raise UnsupportedTokenTypeError(request=request) + def _raise_on_bad_method(self, request): + if self.valid_request_methods is None: + raise ValueError('Configure "valid_request_methods" property first') + if request.http_method.upper() not in self.valid_request_methods: + raise InvalidRequestError(request=request, + description=('Unsupported request method %s' % request.http_method.upper())) + + def _raise_on_bad_post_request(self, request): + """Raise if invalid POST request received + """ + if request.http_method.upper() == 'POST': + query_params = request.uri_query or "" + if query_params: + raise InvalidRequestError(request=request, + description=('URL query parameters are not allowed')) 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 47022fd..4accbdc 100644 --- a/oauthlib/oauth2/rfc6749/endpoints/introspect.py +++ b/oauthlib/oauth2/rfc6749/endpoints/introspect.py @@ -39,6 +39,7 @@ class IntrospectEndpoint(BaseEndpoint): """ valid_token_types = ('access_token', 'refresh_token') + valid_request_methods = ('POST',) def __init__(self, request_validator, supported_token_types=None): BaseEndpoint.__init__(self) @@ -117,6 +118,8 @@ class IntrospectEndpoint(BaseEndpoint): .. _`section 1.5`: http://tools.ietf.org/html/rfc6749#section-1.5 .. _`RFC6749`: http://tools.ietf.org/html/rfc6749 """ + self._raise_on_bad_method(request) + self._raise_on_bad_post_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 fda3f30..1fabd03 100644 --- a/oauthlib/oauth2/rfc6749/endpoints/revocation.py +++ b/oauthlib/oauth2/rfc6749/endpoints/revocation.py @@ -28,6 +28,7 @@ class RevocationEndpoint(BaseEndpoint): """ valid_token_types = ('access_token', 'refresh_token') + valid_request_methods = ('POST',) def __init__(self, request_validator, supported_token_types=None, enable_jsonp=False): @@ -121,6 +122,8 @@ 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 """ + self._raise_on_bad_method(request) + self._raise_on_bad_post_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/token.py b/oauthlib/oauth2/rfc6749/endpoints/token.py index 90fb16f..bc87e9b 100644 --- a/oauthlib/oauth2/rfc6749/endpoints/token.py +++ b/oauthlib/oauth2/rfc6749/endpoints/token.py @@ -62,6 +62,8 @@ class TokenEndpoint(BaseEndpoint): .. _`Appendix B`: https://tools.ietf.org/html/rfc6749#appendix-B """ + valid_request_methods = ('POST',) + def __init__(self, default_grant_type, default_token_type, grant_types): BaseEndpoint.__init__(self) self._grant_types = grant_types @@ -85,13 +87,13 @@ class TokenEndpoint(BaseEndpoint): return self._default_token_type @catch_errors_and_unavailability - def create_token_response(self, uri, http_method='GET', body=None, + def create_token_response(self, uri, http_method='POST', body=None, headers=None, credentials=None, grant_type_for_scope=None, claims=None): """Extract grant_type and route to the designated handler.""" request = Request( uri, http_method=http_method, body=body, headers=headers) - + self.validate_token_request(request) # 'scope' is an allowed Token Request param in both the "Resource Owner Password Credentials Grant" # and "Client Credentials Grant" flows # https://tools.ietf.org/html/rfc6749#section-4.3.2 @@ -115,3 +117,7 @@ class TokenEndpoint(BaseEndpoint): request.grant_type, grant_type_handler) return grant_type_handler.create_token_response( request, self.default_token_type) + + def validate_token_request(self, request): + self._raise_on_bad_method(request) + self._raise_on_bad_post_request(request) diff --git a/oauthlib/oauth2/rfc6749/grant_types/authorization_code.py b/oauthlib/oauth2/rfc6749/grant_types/authorization_code.py index 5f03d9c..9b84c4c 100644 --- a/oauthlib/oauth2/rfc6749/grant_types/authorization_code.py +++ b/oauthlib/oauth2/rfc6749/grant_types/authorization_code.py @@ -405,12 +405,15 @@ class AuthorizationCodeGrant(GrantTypeBase): raise errors.MissingCodeChallengeError(request=request) if request.code_challenge is not None: + request_info["code_challenge"] = request.code_challenge + # OPTIONAL, defaults to "plain" if not present in the request. if request.code_challenge_method is None: request.code_challenge_method = "plain" if request.code_challenge_method not in self._code_challenge_methods: raise errors.UnsupportedCodeChallengeMethodError(request=request) + request_info["code_challenge_method"] = request.code_challenge_method # OPTIONAL. The scope of the access request as described by Section 3.3 # https://tools.ietf.org/html/rfc6749#section-3.3 diff --git a/oauthlib/oauth2/rfc6749/parameters.py b/oauthlib/oauth2/rfc6749/parameters.py index f8d42db..14d4c0d 100644 --- a/oauthlib/oauth2/rfc6749/parameters.py +++ b/oauthlib/oauth2/rfc6749/parameters.py @@ -264,12 +264,15 @@ def parse_authorization_code_response(uri, state=None): query = urlparse.urlparse(uri).query params = dict(urlparse.parse_qsl(query)) - if not 'code' in params: - raise MissingCodeError("Missing code parameter in response.") - if state and params.get('state', None) != state: raise MismatchingStateError() + if 'error' in params: + raise_from_error(params.get('error'), params) + + if not 'code' in params: + raise MissingCodeError("Missing code parameter in response.") + return params diff --git a/oauthlib/oauth2/rfc6749/request_validator.py b/oauthlib/oauth2/rfc6749/request_validator.py index d6ec2ab..86509b6 100644 --- a/oauthlib/oauth2/rfc6749/request_validator.py +++ b/oauthlib/oauth2/rfc6749/request_validator.py @@ -271,6 +271,9 @@ class RequestValidator(object): - Code Challenge (``request.code_challenge``) and - Code Challenge Method (``request.code_challenge_method``) + To support OIDC, you MUST associate the code with: + - nonce, if present (``code["nonce"]``) + The ``code`` argument is actually a dictionary, containing at least a ``code`` key with the actual authorization code: diff --git a/oauthlib/oauth2/rfc6749/tokens.py b/oauthlib/oauth2/rfc6749/tokens.py index 7973923..3587af4 100644 --- a/oauthlib/oauth2/rfc6749/tokens.py +++ b/oauthlib/oauth2/rfc6749/tokens.py @@ -254,7 +254,7 @@ def get_token_from_header(request): if 'Authorization' in request.headers: split_header = request.headers.get('Authorization').split() - if len(split_header) == 2 and split_header[0] == 'Bearer': + if len(split_header) == 2 and split_header[0].lower() == 'bearer': token = split_header[1] else: token = request.access_token @@ -353,7 +353,7 @@ class BearerToken(TokenBase): :param request: OAuthlib request. :type request: oauthlib.common.Request """ - if request.headers.get('Authorization', '').split(' ')[0] == 'Bearer': + if request.headers.get('Authorization', '').split(' ')[0].lower() == 'bearer': return 9 elif request.access_token is not None: return 5 |