From 5f629b5dce3fc6aafb5908480ed241c6f5b4cfbb Mon Sep 17 00:00:00 2001 From: Jonathan Huot Date: Wed, 12 Dec 2018 17:58:45 +0100 Subject: Used WWW-Authenticate and auth-param values as RFC6750 described it. It misses the possibility to add scope= and realm= at the moment, but it should be a step forward into the right direction. --- oauthlib/oauth2/rfc6749/endpoints/introspect.py | 4 +--- oauthlib/oauth2/rfc6749/endpoints/revocation.py | 4 +--- oauthlib/oauth2/rfc6749/errors.py | 21 +++++++++++++++++++++ .../rfc6749/grant_types/authorization_code.py | 3 +-- .../rfc6749/grant_types/client_credentials.py | 3 +-- .../oauth2/rfc6749/grant_types/refresh_token.py | 3 +-- .../resource_owner_password_credentials.py | 3 +-- .../rfc6749/endpoints/test_introspect_endpoint.py | 4 ++-- .../rfc6749/endpoints/test_revocation_endpoint.py | 4 ++-- 9 files changed, 31 insertions(+), 18 deletions(-) diff --git a/oauthlib/oauth2/rfc6749/endpoints/introspect.py b/oauthlib/oauth2/rfc6749/endpoints/introspect.py index ac2e328..4db1bdc 100644 --- a/oauthlib/oauth2/rfc6749/endpoints/introspect.py +++ b/oauthlib/oauth2/rfc6749/endpoints/introspect.py @@ -63,9 +63,7 @@ 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 + return e.headers, e.json, e.status_code claims = self.request_validator.introspect_token( request.token, diff --git a/oauthlib/oauth2/rfc6749/endpoints/revocation.py b/oauthlib/oauth2/rfc6749/endpoints/revocation.py index b13faa3..6c59a1e 100644 --- a/oauthlib/oauth2/rfc6749/endpoints/revocation.py +++ b/oauthlib/oauth2/rfc6749/endpoints/revocation.py @@ -69,9 +69,7 @@ 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 + return e.headers, response_body, e.status_code self.request_validator.revoke_token(request.token, request.token_type_hint, request) diff --git a/oauthlib/oauth2/rfc6749/errors.py b/oauthlib/oauth2/rfc6749/errors.py index addcb6d..e5543b5 100644 --- a/oauthlib/oauth2/rfc6749/errors.py +++ b/oauthlib/oauth2/rfc6749/errors.py @@ -96,6 +96,27 @@ class OAuth2Error(Exception): def json(self): return json.dumps(dict(self.twotuples)) + @property + def headers(self): + if self.status_code == 401: + """ + https://tools.ietf.org/html/rfc6750#section-3 + + All challenges defined by this specification MUST use the auth-scheme + value "Bearer". This scheme MUST be followed by one or more + auth-param values. + """ + authvalues = [ + "Bearer", + "error={}".format(self.error) + ] + if self.description: + authvalues.append("error_description={}".format(self.description)) + if self.uri: + authvalues.append("error_uri={}".format(self.uri)) + return {"WWW-Authenticate": ", ".join(authvalues)} + return {} + class TokenExpiredError(OAuth2Error): error = 'token_expired' diff --git a/oauthlib/oauth2/rfc6749/grant_types/authorization_code.py b/oauthlib/oauth2/rfc6749/grant_types/authorization_code.py index 334ed56..850d70a 100644 --- a/oauthlib/oauth2/rfc6749/grant_types/authorization_code.py +++ b/oauthlib/oauth2/rfc6749/grant_types/authorization_code.py @@ -243,8 +243,7 @@ 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"}) + headers.update(e.headers) 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 54dbebc..0e4f545 100644 --- a/oauthlib/oauth2/rfc6749/grant_types/client_credentials.py +++ b/oauthlib/oauth2/rfc6749/grant_types/client_credentials.py @@ -77,8 +77,7 @@ 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"}) + headers.update(e.headers) 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 d2b3f6f..67d65a7 100644 --- a/oauthlib/oauth2/rfc6749/grant_types/refresh_token.py +++ b/oauthlib/oauth2/rfc6749/grant_types/refresh_token.py @@ -64,8 +64,7 @@ class RefreshTokenGrant(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"}) + headers.update(e.headers) 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 931d76c..cb5a4ca 100644 --- a/oauthlib/oauth2/rfc6749/grant_types/resource_owner_password_credentials.py +++ b/oauthlib/oauth2/rfc6749/grant_types/resource_owner_password_credentials.py @@ -105,8 +105,7 @@ 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"}) + headers.update(e.headers) 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 f7c8033..d252a73 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, {"WWW-Authenticate": "Basic"}) + self.assertEqual(h, {"WWW-Authenticate": "Bearer, error=invalid_client"}) 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, {"WWW-Authenticate": "Basic"}) + self.assertEqual(h, {"WWW-Authenticate": "Bearer, error=invalid_client"}) 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 db562c8..8a434e2 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, {"WWW-Authenticate": "Basic"}) + self.assertEqual(h, {"WWW-Authenticate": "Bearer, error=invalid_client"}) 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, {"WWW-Authenticate": "Basic"}) + self.assertEqual(h, {"WWW-Authenticate": "Bearer, error=invalid_client"}) self.assertEqual(loads(b)['error'], 'invalid_client') self.assertEqual(s, 401) -- cgit v1.2.1