I've seen lots of related questions to this one, but none of the answers have helped me.
First, I went to the Twitter Developer Portal and set up my OAuth2.0 Client ID and Secret:
Then, I used Authlib to set up a OAuth2Session
with an Authorization Code flow, documented here:
authorization_url = 'https://api.twitter.com/2/oauth2/authorize'
scopes = ['tweet.read', 'tweet.write', 'users.read']
scope = ' '.join(scopes)
Then I set up an OAuth2 client using the ID and secret, create the authorization URL, and print the URI for use:
client = OAuth2Session(client_id, client_secret, scope=scope)
uri, state = client.create_authorization_url(authorization_url)
print("> Open this in your browser: " + uri)
In the terminal, it prints
> Open this in your browser: https://api.twitter.com/2/oauth2/authorize?response_type=code&client_id=[redacted]&scope=tweet.read+tweet.write+users.read&state=L21JiPkirR8awYs7kcDjFC4jrPj68x
But opening the link in a browser displays the Twitter-produced error
{"errors":[{"message":"Bad Authentication data","code":215}]}
which is all over Stack Overflow. So I tried
- logging out of Twitter again,
- opening the link on various browsers,
- removing the
scope
parameter from theOAuth2Session
object, - changing the
scope
join character from' '
to'%20'
and'+'
, - double-checking and regenerating Client ID + Secret,
- removing Authlib and implementing the same code using just Python requests
I believe another answer (and others like these) fail to help in my situation because Authlib's OAuth2Session
should be correctly set up and authenticating via OAuth2 (unless there's a problem with the library).
So, after that, I tried adding the callback URI through the client. I used a local callback URI with a Flask app. This is the same Callback URI I set up in the Twitter developer portal. Although this probably isn't done correctly, I don't believe it's causing Error 215. I thought I'd include this just in case:
callback_uri = 'http://127.0.0.1:5000/oauth/callback'
client = OAuth2Session(client_id, client_secret, scope=scope, redirect_uri=callback_uri)
from flask import Flask
app = Flask(__name__)
@app.route("/oauth/callback", methods=["GET"])
def callback():
print('Callback')
I could be missing something, or perhaps my data is improperly formatted in some way. This has proven to be a frustrating issue.