halcy / Mastodon.py

Python wrapper for the Mastodon ( https://github.com/mastodon/mastodon/ ) API.
MIT License
867 stars 150 forks source link

OAuth question #367

Closed eBerdnA closed 5 months ago

eBerdnA commented 5 months ago

I'm somehow stuck understanding how the OAuth flow should be working. My understanding is that I need to get a consent from the user for the app to act on their behalf. Afterwards I can use the obtained OAuth token to login again.

init.py

import webbrowser
import time
from mastodon import Mastodon

m = Mastodon(
    client_id="clientcred.secret",
    api_base_url="https://chaos.social",
)
SCOPES_TO_REQUEST = ['read', 'read:bookmarks', 'read:favourites', 'read:lists', 'follow']
oauth_url = m.auth_request_url(scopes=SCOPES_TO_REQUEST)
webbrowser.open_new(oauth_url)
time.sleep(3)
print("\n\n")

# Get oauth code from user and log in
oauth_code = input("After logging in, enter the code you received: ")

m.log_in(
    code=oauth_code,
    to_file='user_credential_temp.secret',
    scopes=SCOPES_TO_REQUEST
)
user_name = m.me().acct
print(user_name)
lists = m.lists()
print(lists)

The above one works as expected.

lists.py

import webbrowser
import time
from mastodon import Mastodon

SCOPES_TO_REQUEST = ['read', 'read:bookmarks', 'read:favourites', 'read:lists', 'follow']
m = Mastodon(
    client_id="clientcred.secret",
    api_base_url="https://chaos.social",
)

oauth_code = <oauth_code_obtained_from_init.py>
m.log_in(
    code=oauth_code,
    to_file='user_credential_temp.secret',
    scopes=SCOPES_TO_REQUEST
)
lists = m.lists()
print(lists)

But running lists.py results in Invalid access token or redirect_uris: ('Mastodon API returned error', 400, 'Bad Request', 'invalid_grant').

What am I missing?

halcy commented 5 months ago

Hey, to clarify: The oauth code - the thing your user copy-pastes, or that you get via the callback URL if you use that flow, will work exactly once. You use this to log in, and you get an access token (you get the same type of token no matter how you log in, be that via password flow, oauth, whatever). This is what log_in returns, and will write to the file specified by to_file. Afterwards, you just use that file, or that token:

m = Mastodon(access_token = 'user_credential_temp.secret')

and that's that, you now have access. This is the thing you should persist (and should avoid posting publicly). The oauth code is just a temporary value that you can discard later.

Does that answer your questions?

eBerdnA commented 5 months ago

Yes and thanks for your answer. I just realized that my misassumption was that I still needed to execute log_in() in subsequent runs. That sent me down the wrong path.