From 2b835073cb193ca6f2849c8cb6ef4322e5b16f24 Mon Sep 17 00:00:00 2001 From: Harmon Date: Fri, 7 Jan 2022 01:51:01 -0600 Subject: [PATCH] Add OAuth2Handler --- tweepy/__init__.py | 2 +- tweepy/auth.py | 38 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 37 insertions(+), 3 deletions(-) diff --git a/tweepy/__init__.py b/tweepy/__init__.py index 4a93eb3..6db021d 100644 --- a/tweepy/__init__.py +++ b/tweepy/__init__.py @@ -10,7 +10,7 @@ __author__ = 'Joshua Roesslein' __license__ = 'MIT' from tweepy.api import API -from tweepy.auth import AppAuthHandler, OAuthHandler +from tweepy.auth import AppAuthHandler, OAuthHandler, OAuth2Handler from tweepy.cache import Cache, FileCache, MemoryCache from tweepy.client import Client, Response from tweepy.cursor import Cursor diff --git a/tweepy/auth.py b/tweepy/auth.py index 88d0ba8..3f92dd1 100644 --- a/tweepy/auth.py +++ b/tweepy/auth.py @@ -2,12 +2,15 @@ # Copyright 2009-2022 Joshua Roesslein # See LICENSE for details. +from base64 import urlsafe_b64encode +from hashlib import sha256 import logging from urllib.parse import parse_qs +import secrets import requests -from requests.auth import AuthBase -from requests_oauthlib import OAuth1, OAuth1Session +from requests.auth import AuthBase, HTTPBasicAuth +from requests_oauthlib import OAuth1, OAuth1Session, OAuth2Session from tweepy.errors import TweepyException @@ -130,7 +133,38 @@ class OAuthHandler(AuthHandler): raise TweepyException(e) +class OAuth2Handler(OAuth2Session): + + def __init__(self, *, client_id, redirect_uri, scope, client_secret=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 + + def get_authorization_url(self): + self.code_verifier = secrets.token_urlsafe(128)[:128] + code_challenge = urlsafe_b64encode( + sha256(self.code_verifier.encode("ASCII")).digest() + ).rstrip(b'=') + authorization_url, state = self.authorization_url( + "https://twitter.com/i/oauth2/authorize", + code_challenge=code_challenge, code_challenge_method="s256" + ) + return authorization_url + + def fetch_token(self, authorization_response): + return super().fetch_token( + "https://api.twitter.com/2/oauth2/token", + authorization_response=authorization_response, + auth=self.auth, + include_client_id=True, + code_verifier=self.code_verifier + ) + + class OAuth2Bearer(AuthBase): + def __init__(self, bearer_token): self.bearer_token = bearer_token -- 2.25.1