Skip to content

Possible to auto refresh client_credentials access token? #260

@jaddison

Description

@jaddison

As a client_credentials based access token has no refresh token, the refresh_token() functionality raises an exception (ie. InvalidRequestError: Missing refresh token parameter.). Based on the spec, I believe this is technically fine - one should fetch a new access token in this case.

Is it just the spec that prevents requests-oauthlib from handling this scenario gracefully alongside the current token expiration code handling in the request() method on OAuth2Session?

If I subclass OAuth2Session like so:

class RefreshOAuth2Session(OAuth2Session):
    def request(self, *args, **kwargs):
        try:
            return super().request(*args, **kwargs)
        except TokenExpiredError:
            self.token = self.fetch_token(
                token_url=OAUTH2_TOKEN_URL,
                **self.auto_refresh_kwargs
            )
            self.token_updater(self.token)
            return super().request(*args, **kwargs)

I can use it like this:

class MyClass(object):
    _session = None
    _token = None

    def token_updater(self, token):
        self._token = token

    @property
    def session(self):
        if self._session is None:
            self._session = RefreshOAuth2Session(
                client=BackendApplicationClient(client_id=self.client_id),
                token=self.token,
                token_updater=self.token_updater,
                auto_refresh_kwargs={
                    'client_id': self.client_id,
                    'client_secret': self.client_secret,
                }
            )
        return self._session

    @property
    def token(self):
        if self._token is None:
            self._token = RefreshOAuth2Session(
                client=BackendApplicationClient(client_id=self.client_id)
            ).fetch_token(
                token_url=OAUTH2_TOKEN_URL,
                client_id=self.client_id,
                client_secret=self.client_secret
            )
        return self._token

    def __init__(self, *args, **kwargs):
        super(MyClass, self).__init__(*args, **kwargs)
        self.client_id = CLIENT_ID
        self.client_secret = CLIENT_SECRET

    def get_information(self):
        return self.session.get('https://localhost:10000/api/infomation/')


obj = MyClass()
obj.get_information()

As long as auto_refresh_url is not passed in, the logic in my subclass handles everything smoothly. Could logic be added to request() to cover this scenario, rather than having to kludge this as I've done?

Related thread: https://groups.google.com/d/msg/django-oauth-toolkit/iSIiZQtn0mM/5SDckbyTCQAJ

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions