summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Huot <jonathan.huot@thomsonreuters.com>2018-12-04 16:08:13 +0100
committerJonathan Huot <jonathan.huot@thomsonreuters.com>2018-12-04 16:08:13 +0100
commitffa87c7ec828e5c0a7c68a2197030f20b15ec621 (patch)
treeb3e8333ee50b9348adce4d2782e0e6889808f96c
parent51c927b0641adcef6e5944c9a67ba1d7edc2eb68 (diff)
downloadoauthlib-ffa87c7ec828e5c0a7c68a2197030f20b15ec621.tar.gz
Handle 401 with WWW-Authenticate. Moved wrong 401 into 400.
access_denied/unauthorized_client/consent_required/login_required MUST be 400, and not 401. Also, 401 MUST have WWW-Authenticate when set. It could have an impact of processing those in webframeworks.
-rw-r--r--oauthlib/oauth2/rfc6749/endpoints/introspect.py2
-rw-r--r--oauthlib/oauth2/rfc6749/endpoints/revocation.py2
-rw-r--r--oauthlib/oauth2/rfc6749/errors.py8
-rw-r--r--oauthlib/oauth2/rfc6749/grant_types/authorization_code.py2
-rw-r--r--oauthlib/oauth2/rfc6749/grant_types/client_credentials.py2
-rw-r--r--oauthlib/oauth2/rfc6749/grant_types/refresh_token.py3
-rw-r--r--oauthlib/oauth2/rfc6749/grant_types/resource_owner_password_credentials.py2
-rw-r--r--tests/oauth2/rfc6749/endpoints/test_introspect_endpoint.py4
-rw-r--r--tests/oauth2/rfc6749/endpoints/test_revocation_endpoint.py4
9 files changed, 19 insertions, 10 deletions
diff --git a/oauthlib/oauth2/rfc6749/endpoints/introspect.py b/oauthlib/oauth2/rfc6749/endpoints/introspect.py
index 7613acc..ac2e328 100644
--- a/oauthlib/oauth2/rfc6749/endpoints/introspect.py
+++ b/oauthlib/oauth2/rfc6749/endpoints/introspect.py
@@ -63,6 +63,8 @@ class IntrospectEndpoint(BaseEndpoint):
log.debug('Token introspect valid for %r.', request)
except OAuth2Error as e:
log.debug('Client error during validation of %r. %r.', request, e)
+ if e.status_code == 401:
+ return {"WWW-Authenticate": "Basic"}, e.json, e.status_code
return {}, e.json, e.status_code
claims = self.request_validator.introspect_token(
diff --git a/oauthlib/oauth2/rfc6749/endpoints/revocation.py b/oauthlib/oauth2/rfc6749/endpoints/revocation.py
index d5b5b78..b13faa3 100644
--- a/oauthlib/oauth2/rfc6749/endpoints/revocation.py
+++ b/oauthlib/oauth2/rfc6749/endpoints/revocation.py
@@ -69,6 +69,8 @@ class RevocationEndpoint(BaseEndpoint):
response_body = e.json
if self.enable_jsonp and request.callback:
response_body = '%s(%s);' % (request.callback, response_body)
+ if e.status_code == 401:
+ return {"WWW-Authenticate": "Basic"}, response_body, e.status_code
return {}, response_body, e.status_code
self.request_validator.revoke_token(request.token,
diff --git a/oauthlib/oauth2/rfc6749/errors.py b/oauthlib/oauth2/rfc6749/errors.py
index 678fcff..addcb6d 100644
--- a/oauthlib/oauth2/rfc6749/errors.py
+++ b/oauthlib/oauth2/rfc6749/errors.py
@@ -185,7 +185,6 @@ class AccessDeniedError(OAuth2Error):
The resource owner or authorization server denied the request.
"""
error = 'access_denied'
- status_code = 401
class UnsupportedResponseTypeError(OAuth2Error):
@@ -198,12 +197,12 @@ class UnsupportedResponseTypeError(OAuth2Error):
class InvalidScopeError(OAuth2Error):
"""
- The requested scope is invalid, unknown, or malformed.
+ The requested scope is invalid, unknown, or malformed, or
+ exceeds the scope granted by the resource owner.
https://tools.ietf.org/html/rfc6749#section-5.2
"""
error = 'invalid_scope'
- status_code = 400
class ServerError(OAuth2Error):
@@ -261,7 +260,6 @@ class UnauthorizedClientError(OAuth2Error):
grant type.
"""
error = 'unauthorized_client'
- status_code = 401
class UnsupportedGrantTypeError(OAuth2Error):
@@ -318,7 +316,6 @@ class ConsentRequired(OAuth2Error):
completed without displaying a user interface for End-User consent.
"""
error = 'consent_required'
- status_code = 401
class LoginRequired(OAuth2Error):
@@ -330,7 +327,6 @@ class LoginRequired(OAuth2Error):
completed without displaying a user interface for End-User authentication.
"""
error = 'login_required'
- status_code = 401
class CustomOAuth2Error(OAuth2Error):
diff --git a/oauthlib/oauth2/rfc6749/grant_types/authorization_code.py b/oauthlib/oauth2/rfc6749/grant_types/authorization_code.py
index 8ebae49..334ed56 100644
--- a/oauthlib/oauth2/rfc6749/grant_types/authorization_code.py
+++ b/oauthlib/oauth2/rfc6749/grant_types/authorization_code.py
@@ -243,6 +243,8 @@ class AuthorizationCodeGrant(GrantTypeBase):
log.debug('Token request validation ok for %r.', request)
except errors.OAuth2Error as e:
log.debug('Client error during validation of %r. %r.', request, e)
+ if e.status_code == 401:
+ headers.update({"WWW-Authenticate": "Basic"})
return headers, e.json, e.status_code
token = token_handler.create_token(request, refresh_token=self.refresh_token, save_token=False)
diff --git a/oauthlib/oauth2/rfc6749/grant_types/client_credentials.py b/oauthlib/oauth2/rfc6749/grant_types/client_credentials.py
index 7d4f74c..54dbebc 100644
--- a/oauthlib/oauth2/rfc6749/grant_types/client_credentials.py
+++ b/oauthlib/oauth2/rfc6749/grant_types/client_credentials.py
@@ -77,6 +77,8 @@ class ClientCredentialsGrant(GrantTypeBase):
self.validate_token_request(request)
except errors.OAuth2Error as e:
log.debug('Client error in token request. %s.', e)
+ if e.status_code == 401:
+ headers.update({"WWW-Authenticate": "Basic"})
return headers, e.json, e.status_code
token = token_handler.create_token(request, refresh_token=False, save_token=False)
diff --git a/oauthlib/oauth2/rfc6749/grant_types/refresh_token.py b/oauthlib/oauth2/rfc6749/grant_types/refresh_token.py
index 5f7382a..d2b3f6f 100644
--- a/oauthlib/oauth2/rfc6749/grant_types/refresh_token.py
+++ b/oauthlib/oauth2/rfc6749/grant_types/refresh_token.py
@@ -63,6 +63,9 @@ class RefreshTokenGrant(GrantTypeBase):
log.debug('Validating refresh token request, %r.', request)
self.validate_token_request(request)
except errors.OAuth2Error as e:
+ log.debug('Client error in token request, %s.', e)
+ if e.status_code == 401:
+ headers.update({"WWW-Authenticate": "Basic"})
return headers, e.json, e.status_code
token = token_handler.create_token(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 87e8015..931d76c 100644
--- a/oauthlib/oauth2/rfc6749/grant_types/resource_owner_password_credentials.py
+++ b/oauthlib/oauth2/rfc6749/grant_types/resource_owner_password_credentials.py
@@ -105,6 +105,8 @@ class ResourceOwnerPasswordCredentialsGrant(GrantTypeBase):
self.validate_token_request(request)
except errors.OAuth2Error as e:
log.debug('Client error in token request, %s.', e)
+ if e.status_code == 401:
+ headers.update({"WWW-Authenticate": "Basic"})
return headers, e.json, e.status_code
token = token_handler.create_token(request, self.refresh_token, save_token=False)
diff --git a/tests/oauth2/rfc6749/endpoints/test_introspect_endpoint.py b/tests/oauth2/rfc6749/endpoints/test_introspect_endpoint.py
index 7ec8190..f7c8033 100644
--- a/tests/oauth2/rfc6749/endpoints/test_introspect_endpoint.py
+++ b/tests/oauth2/rfc6749/endpoints/test_introspect_endpoint.py
@@ -86,7 +86,7 @@ class IntrospectEndpointTest(TestCase):
('token_type_hint', 'access_token')])
h, b, s = self.endpoint.create_introspect_response(self.uri,
headers=self.headers, body=body)
- self.assertEqual(h, {})
+ self.assertEqual(h, {"WWW-Authenticate": "Basic"})
self.assertEqual(loads(b)['error'], 'invalid_client')
self.assertEqual(s, 401)
@@ -109,7 +109,7 @@ class IntrospectEndpointTest(TestCase):
('token_type_hint', 'access_token')])
h, b, s = self.endpoint.create_introspect_response(self.uri,
headers=self.headers, body=body)
- self.assertEqual(h, {})
+ self.assertEqual(h, {"WWW-Authenticate": "Basic"})
self.assertEqual(loads(b)['error'], 'invalid_client')
self.assertEqual(s, 401)
diff --git a/tests/oauth2/rfc6749/endpoints/test_revocation_endpoint.py b/tests/oauth2/rfc6749/endpoints/test_revocation_endpoint.py
index 77f5662..db562c8 100644
--- a/tests/oauth2/rfc6749/endpoints/test_revocation_endpoint.py
+++ b/tests/oauth2/rfc6749/endpoints/test_revocation_endpoint.py
@@ -49,7 +49,7 @@ class RevocationEndpointTest(TestCase):
('token_type_hint', 'access_token')])
h, b, s = self.endpoint.create_revocation_response(self.uri,
headers=self.headers, body=body)
- self.assertEqual(h, {})
+ self.assertEqual(h, {"WWW-Authenticate": "Basic"})
self.assertEqual(loads(b)['error'], 'invalid_client')
self.assertEqual(s, 401)
@@ -72,7 +72,7 @@ class RevocationEndpointTest(TestCase):
('token_type_hint', 'access_token')])
h, b, s = self.endpoint.create_revocation_response(self.uri,
headers=self.headers, body=body)
- self.assertEqual(h, {})
+ self.assertEqual(h, {"WWW-Authenticate": "Basic"})
self.assertEqual(loads(b)['error'], 'invalid_client')
self.assertEqual(s, 401)