requests / requests-oauthlib

OAuthlib support for Python-Requests!
https://requests-oauthlib.readthedocs.org/
ISC License
1.73k stars 423 forks source link

refactor: Add support for auto-refreshing token without refresh token #526

Open dabla opened 10 months ago

dabla commented 10 months ago

Hello,

This is a pull request based on the changes made by @denizdogan but which finally never got merged due to missing tests.

Here is the original explaination:

This is a basic idea on how to fix https://github.com/requests/requests-oauthlib/issues/260 since nothing has happened to the issue in three years. Let's get a discussion going, because this is a hindrance to me in almost every OAuth2 implementation I make using this library and it's clear that lots of other people have the same issue.

So the idea is to add a new constructor parameter which I currently call auto_refresh_type, it can be either "refresh_token" (which will do exactly what it does today) or "access_token" (which will just get a new access token as you normally do).

It's not a beautiful design by any means, but I intentionally tried to keep the diff as minimal as possible without any major refactorings, which would introduce breaking changes and make it more difficult to get this functionality out there.

I've done some minor refactoring but also added 2 tests which test both cases when the update_token method is invoked.

Kind regards, David

jtroussard commented 8 months ago

@dabla Is it possible to update this PR/fix conflicts. This will kick off the test runners and I will have a look and try to get this merged.

jtroussard commented 8 months ago

for documentation purposes, linking these related resources.

394 #260

issue and pr related to previous attempts to get this feature merged.

zach-flaglerhealth commented 3 months ago

For anyone coming across this PR and thinking about vendoring in this particular PR...

To utilize this, following the basic BackendApplicationClient example from the docs, you'll need to add the following parameters to your OAuth2Session:

client = BackendApplicationClient(client_id="some_client_id", scope="your scopes here") # No changes
oauth = OAuth2Session(
    client=client,
    client_id="some_client_id",
    # New params
    auto_refresh_type="access_token",
    auto_refresh_url="The OAuth2 token URL",
    auto_refresh_kwargs={"client_secret": "Your client secret"}
)

The reason you need to pass it in there is that the Session tries to either utilize the auth attribute it's passing around, or tries re-encoding the client_id and client_secret. However, the class doesn't like it as an attribute, but does properly get pulled into fetch_token.

There are two other changes I made for my purposes, which may be more controversial:

  1. I removed the raise TokenUpdated(token), since the whole point of the session is to handle this for me.
  2. I copied the self._client.add_token from lines 528 - 530, because otherwise it just continues to make the request with the invalid token.

There may be things I've overlooked. My changes make the tests that were added here fail (since they're looking for a raised exception). This seems to now be running and auto-refreshing for me.