summaryrefslogtreecommitdiff
path: root/oauthlib/oauth2
diff options
context:
space:
mode:
Diffstat (limited to 'oauthlib/oauth2')
-rw-r--r--oauthlib/oauth2/rfc6749/clients/backend_application.py1
-rw-r--r--oauthlib/oauth2/rfc6749/endpoints/base.py31
-rw-r--r--oauthlib/oauth2/rfc6749/endpoints/introspect.py3
-rw-r--r--oauthlib/oauth2/rfc6749/endpoints/revocation.py3
-rw-r--r--oauthlib/oauth2/rfc6749/endpoints/token.py10
-rw-r--r--oauthlib/oauth2/rfc6749/parameters.py14
6 files changed, 55 insertions, 7 deletions
diff --git a/oauthlib/oauth2/rfc6749/clients/backend_application.py b/oauthlib/oauth2/rfc6749/clients/backend_application.py
index 2483e56..5737814 100644
--- a/oauthlib/oauth2/rfc6749/clients/backend_application.py
+++ b/oauthlib/oauth2/rfc6749/clients/backend_application.py
@@ -71,5 +71,6 @@ class BackendApplicationClient(Client):
"""
kwargs['client_id'] = self.client_id
kwargs['include_client_id'] = include_client_id
+ scope = self.scope if scope is None else scope
return prepare_token_request(self.grant_type, body=body,
scope=scope, **kwargs)
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/parameters.py b/oauthlib/oauth2/rfc6749/parameters.py
index 6b9d630..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
@@ -419,7 +422,10 @@ def parse_token_response(body, scope=None):
params['scope'] = scope_to_list(params['scope'])
if 'expires_in' in params:
- params['expires_at'] = time.time() + int(params['expires_in'])
+ if params['expires_in'] is None:
+ params.pop('expires_in')
+ else:
+ params['expires_at'] = time.time() + int(params['expires_in'])
params = OAuth2Token(params, old_scope=scope)
validate_token_parameters(params)