From 67b77567a4ad3709d29294548447dd6802d2e558 Mon Sep 17 00:00:00 2001 From: Eric Toombs Date: Thu, 19 Jan 2023 17:04:02 -0500 Subject: [PATCH] Implement OAuth2 user token autorefresh. OAuth2 user authentication is now handled by OAuth2UserHandler as a session. To make it work, pass an OAuth2UserHandler to the session argument of Client's constructor. --- tweepy/auth.py | 26 +++++++++++++++++++++++++- tweepy/client.py | 25 +++++++++++++------------ 2 files changed, 38 insertions(+), 13 deletions(-) diff --git a/tweepy/auth.py b/tweepy/auth.py index 93fc30237..4dd1fc8b0 100644 --- a/tweepy/auth.py +++ b/tweepy/auth.py @@ -193,13 +193,37 @@ class OAuth2UserHandler(OAuth2Session): .. versionadded:: 4.5 """ - def __init__(self, *, client_id, redirect_uri, scope, client_secret=None): + def __init__( + self, *, client_id, redirect_uri, scope, client_secret=None, + auto_refresh=True, token_updater=None + ): super().__init__(client_id, redirect_uri=redirect_uri, scope=scope) + if client_secret is not None: self.auth = HTTPBasicAuth(client_id, client_secret) else: self.auth = None + if auto_refresh: + self.token_updater = token_updater + self.auto_refresh_url = 'https://api.twitter.com/2/oauth2/token' + self.auto_refresh_kwargs = {'client_id': client_id} + + @classmethod + def from_token( + cls, token, *, client_id, redirect_uri, client_secret=None, + token_updater=None + ): + """Make an OAuth2UserHandler from a token dict returned by + fetch_token() or from the .token field in a previous session.""" + h = cls( + client_id=client_id, redirect_uri=redirect_uri, + scope=token['scope'], client_secret=client_secret, + token_updater=token_updater + ) + h.token = token + return h + def get_authorization_url(self): """Get the authorization URL to redirect the user to""" authorization_url, state = self.authorization_url( diff --git a/tweepy/client.py b/tweepy/client.py index 440a15535..014bc5d3f 100644 --- a/tweepy/client.py +++ b/tweepy/client.py @@ -41,11 +41,12 @@ class BaseClient: def __init__( - self, bearer_token=None, consumer_key=None, consumer_secret=None, - access_token=None, access_token_secret=None, *, return_type=Response, - wait_on_rate_limit=False + self, bearer_token=None, session=requests.Session(), consumer_key=None, + consumer_secret=None, access_token=None, access_token_secret=None, *, + return_type=Response, wait_on_rate_limit=False ): self.bearer_token = bearer_token + self.session = session self.consumer_key = consumer_key self.consumer_secret = consumer_secret self.access_token = access_token @@ -54,7 +55,6 @@ def __init__( self.return_type = return_type self.wait_on_rate_limit = wait_on_rate_limit - self.session = requests.Session() self.user_agent = ( f"Python/{python_version()} " f"Requests/{requests.__version__} " @@ -65,14 +65,15 @@ def request(self, method, route, params=None, json=None, user_auth=False): host = "https://api.twitter.com" headers = {"User-Agent": self.user_agent} auth = None - if user_auth: - auth = OAuth1UserHandler( - self.consumer_key, self.consumer_secret, - self.access_token, self.access_token_secret - ) - auth = auth.apply_auth() - else: - headers["Authorization"] = f"Bearer {self.bearer_token}" + if type(self.session) == requests.Session: + if user_auth: + auth = OAuth1UserHandler( + self.consumer_key, self.consumer_secret, + self.access_token, self.access_token_secret + ) + auth = auth.apply_auth() + else: + headers["Authorization"] = f"Bearer {self.bearer_token}" log.debug( f"Making API request: {method} {host + route}\n"