From d5104edcb12770a8c8c09b410a747a0de6628383 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micka=C3=ABl=20Schoentgen?= Date: Tue, 20 Apr 2021 14:33:55 +0200 Subject: [PATCH] NXPY-201: Allow more extensability of request_token() Also simplified the `OAuth2Error` exception as the stacktrace was not useful. --- examples/authentication.rst | 12 +++++++++++- nuxeo/auth/oauth2.py | 20 ++++++++++++-------- nuxeo/exceptions.py | 10 +++++----- tests/test_exception.py | 4 ++-- 4 files changed, 30 insertions(+), 16 deletions(-) diff --git a/examples/authentication.rst b/examples/authentication.rst index 952bc586..19f683a0 100644 --- a/examples/authentication.rst +++ b/examples/authentication.rst @@ -62,7 +62,17 @@ Scenario 1: Generating a New Token authorization_response = req.url # Step 3, get the token - token = nuxeo.client.auth.request_token(authorization_response, code_verifier) + token = nuxeo.client.auth.request_token( + code_verifier=code_verifier, + authorization_response=authorization_response, + ) + + # Step 3, another possibility when you already parsed *authorization_response* and know the *code* + token = nuxeo.client.auth.request_token( + code_verifier=code_verifier, + code=code, + state=state, + ) Scenario 2: Using an Existing Token diff --git a/nuxeo/auth/oauth2.py b/nuxeo/auth/oauth2.py index 27530eed..fa02b380 100644 --- a/nuxeo/auth/oauth2.py +++ b/nuxeo/auth/oauth2.py @@ -4,7 +4,7 @@ from time import time from authlib.common.security import generate_token -from authlib.integrations.base_client.errors import OAuthError +from authlib.integrations.base_client.errors import AuthlibBaseError from authlib.integrations.requests_client import OAuth2Session from authlib.oauth2.rfc7636 import create_s256_code_challenge @@ -77,9 +77,9 @@ def _request(self, method, *args, **kwargs): """Make a request with the OAuthlib client and shadow exceptions.""" try: return method(*args, **kwargs) - except OAuthError as exc: + except AuthlibBaseError as exc: # TODO NXPY-129: Use raise ... from None - raise OAuth2Error(exc.error, exc.description) + raise OAuth2Error(exc.description) def token_is_expired(self): # type: () -> bool @@ -102,15 +102,19 @@ def create_authorization_url(self, **kwargs): ) return uri, state, code_verifier - def request_token(self, authorization_response, code_verifier): - # type: (Text, Text) -> None - """Do request for a token.""" + def request_token(self, **kwargs): + # type: (Any) -> None + """Do request for a token. + The *code_verifier* kwarg is required in any cases. + Other kwargs can be a combination of either: + 1. *authorization_response* or; + 2. *code* and *state*. + """ token = self._request( self._client.fetch_token, self._token_endpoint, grant_type=self.GRANT_AUTHORIZATION_CODE, - authorization_response=authorization_response, - code_verifier=code_verifier, + **kwargs ) self.set_token(token) return token diff --git a/nuxeo/exceptions.py b/nuxeo/exceptions.py index 784da518..adaad2bc 100644 --- a/nuxeo/exceptions.py +++ b/nuxeo/exceptions.py @@ -124,14 +124,14 @@ def __str__(self): class OAuth2Error(HTTPError): - """ Exception thown when an OAuth2 error happens. """ + """ Exception thrown when an OAuth2 error happens. """ status = 400 - def __init__(self, error, description): - # type: (Text, Text) -> None - self.stacktrace = error - self.message = description + def __init__(self, error): + # type: (Text) -> None + self.message = error + self.stacktrace = None class OngoingRequestError(Conflict): diff --git a/tests/test_exception.py b/tests/test_exception.py index 76f076cb..59853cf8 100644 --- a/tests/test_exception.py +++ b/tests/test_exception.py @@ -52,11 +52,11 @@ def test_crafted_httperror_parse(): def test_crafted_oauth2_error(): - exc = OAuth2Error("invalid_grant", "Cannot refresh token") + exc = OAuth2Error("Cannot refresh token") assert str(exc) assert exc.status == 400 assert exc.message == "Cannot refresh token" - assert exc.stacktrace == "invalid_grant" + assert not exc.stacktrace def test_crafted_ongoing_request_error():