requests-oauthlib icon indicating copy to clipboard operation
requests-oauthlib copied to clipboard

Getting new tokens automagically, or "fake refresh"

Open lvh opened this issue 9 years ago • 6 comments

I have an API for a backend web application that does not provide me with refresh tokens. My understanding is that this is reasonably common; since the backend application already has the credentials anyway, the usual reason for having tokens and refresh tokens goes away.

Even though there is no refresh token, the original token still expires as normal. It'd be great if the automagic refresh behavior (normally using refresh) tokens also existed for when you don't have those tokens, but do have the requisite credentials to just acquire a new token anyway.

The fetch_token API appears to require me to specify API-specific features when I call that API: the token endpoint, scope, and credentials. I may have missed it, but there doesn't seem to be a place to store that state as e.g. part of the session.

This may be solvable compositionally, of course. I'll probably write something to fix this myself. Would you be interested in having it upstreamed? Am I just missing the Right(TM) API?

lvh avatar Jul 18 '16 20:07 lvh

You're right, this appears to not be currently supported. This is a low priority maintenance project for me, but I'd be willing to accept a patch that implemented this functionality if you're prepared to write it!

Lukasa avatar Jul 18 '16 20:07 Lukasa

Sounds good. I'll see how I end up working around this problem and contribute it if it's halfway decent.

lvh avatar Jul 18 '16 20:07 lvh

FYI, I ended up being rather unhappy about the way this looks, since requests.Session is hard to write useful wrappers for (lots of helper methods like get that should also use the new request impl).

lvh avatar Jul 20 '16 19:07 lvh

Could this issue be addressed by changes proposed here?

https://github.com/requests/requests-oauthlib/issues/264

btimby avatar Mar 03 '17 14:03 btimby

I'm also dealing with an API that doesn't provide refresh tokens. Once my token expires I have to request a new one. I wasn't able to get automatic refreshing working without a refresh token. This isn't ideal and may not be pretty, but I was able to monkey patch the refresh_token method for my specific use case.

def refresh_token(self, token_url, *args, **kwargs):
    """
    Used to monkey patch OAuth2Session.refresh_token() to allow auto-token-refreshing.
    """
    token = self.fetch_token(
        token_url=token_url,
        client_id=self.client_id,
        client_secret=self.auto_refresh_kwargs["client_secret"],
        scope=self.scope,
    )

    def token_updater(*args, **kwargs):
        """Used to monkey patch the required token_updater function."""
        pass

    self.token_updater = token_updater
    # Save the new token in the OAuth2Session object for later use
    self.token = token
    self.access_token = token["access_token"]
    return token

Mike-Nahmias avatar May 01 '20 18:05 Mike-Nahmias

To solve this I made the refresh_token mock for my fetch_token application:


client = BackendApplicationClient(client_id=values["client_id"])
oauth = OAuth2Session(
    client=client,
    auto_refresh_url=values["url"],
    auto_refresh_kwargs=dict(client_id=values["client_id"], client_secret=values["client_secret"]),
)

# include_client_id because client_id must be in body, in my app!
def mock_refresh_token(*args, **kwargs):
    return oauth.fetch_token(
        oauth.auto_refresh_url,
        include_client_id=True,
        **oauth.auto_refresh_kwargs,
    )

oauth.refresh_token = mock_refresh_token
oauth.refresh_token()

ghost avatar May 25 '22 22:05 ghost