xero-python icon indicating copy to clipboard operation
xero-python copied to clipboard

Assert on token format caused by inconsistency with authlib

Open JargeZ opened this issue 1 year ago • 0 comments

The library has a check can_refresh_access_token inside which isinstance(self.scope, (list, tuple)) is checked Otherwise the access token is not refreshed and fails with an error

It would be better if an error occurred when trying to initialize the library with a scope as a string, or perform an automatic split occurred.

I'm not sure which strategy others will consider better.

For context, I was run into a scope parameter inconsistency issue with the authlib library

I first authorize the user like this

oauth = OAuth()
oauth.register(
    name="xero",
    version="2",
    client_id=env_settings.XERO_CLIENT_ID,
    client_secret=env_settings.XERO_CLIENT_SECRET,
    endpoint_url="https://api.xero.com/",
    authorization_endpoint="https://login.xero.com/identity/connect/authorize",
    access_token_url="https://identity.xero.com/connect/token",
    refresh_token_url="https://identity.xero.com/connect/token",
    scope="offline_access openid profile email accounting.transactions "
        "accounting.transactions.read accounting.reports.read "
        "accounting.journals.read accounting.settings accounting.settings.read "
        "accounting.contacts accounting.contacts.read accounting.attachments "
        "accounting.attachments.read assets projects",
    jwks_uri="https://identity.xero.com/.well-known/openid-configuration/jwks",
)
return oauth

and in the saved token the scope has the type string with spaces. Then I worked with the API and did not understand why the token could not be updated.

class XeroAuthViewSet(viewsets.ViewSet):
    @action(detail=False, methods=["get"], name="oauth-callback")
    def oauth_callback(self, request):
        token: OAuth2Token = oauth.xero.authorize_access_token(request)

        if token is None:
            return HttpResponse("Access Denied")

        save_token(
            user=request.user,
            token=token,
        )

        return redirect("/backend/tenants/")

The solution to the problem is to transform the token when saving it for the first time on the application side.

JargeZ avatar Jul 26 '24 02:07 JargeZ