I signed up for a new instance and noticed that Mastodon Archive doesn’t allow me to log in using OAuth2. What’s going on? Let’s look at the API again.
Register the application:
curl -X POST -d "client_name=mastodon-archive&redirect_uris=urn:ietf:wg:oauth:2.0:oob&scopes=read" -Ss https://tabletop.social/api/v1/apps
This gives me a JSON containing client_id and client_secret. Store these as environment variables of the same name.
Store the password in an environment variable, too.
export client_id=... export client_secret=... export password=...
Login to get the access token:
curl -X POST -d "client_id=$client_id&client_secret=$client_secret&grant_type=password&username=kensanata@gmail.com&password=$password" -Ss https://tabletop.social/oauth/token
Store it in an environment variable, of course.
export access=token=...
Test it:
curl --header "Authorization: Bearer $access_token" -sS https://tabletop.social/api/v1/timelines/home
This seems to work even though it doesn’t work for Mastodon Archive!
Let’s create the necessary files, manually:
echo $client_id > tabletop.social.client.secret echo $client_secret >> tabletop.social.client.secret echo $access_token > tabletop.social.user.kensanata.secret
And test it:
$ mastodon-archive archive kensanata@tabletop.social Get user info Get statuses (this may take a while) Get favourites (this may take a while) Skipping mentions Skipping followers Saving 33 statuses, 13 favourites, 0 mentions, and 0 followers
Thus, we now know that the problem is the app registration and obtaining the access token. Everything else works as expected.
Tags: Mastodon
Comments
Debugging what
Mastodon.pydoes... Here is what my code does, essentially:print("Registering app") Mastodon.create_app( 'mastodon-archive', api_base_url = url, to_file = client_secret) print("Log in") mastodon = Mastodon( client_id = client_secret, api_base_url = url, debug_requests = True) url = mastodon.auth_request_url( client_id = client_secret, scopes=scopes) print("Visit the following URL and authorize the app:") print(url) print("Then paste the access token here:") token = sys.stdin.readline().rstrip() mastodon.log_in( username = username, code = token, to_file = user_secret, scopes=scopes)And I get the error in the last statement.
Registering app Log in Mastodon: Request to endpoint "/api/v1/instance/" using method "GET". Parameters: {} Headers: None Files: {} Mastodon: Response received with code 200. response headers: {...} Response text content: {...} Visit the following URL and authorize the app: https://social.nasqueron.org/oauth/authorize?client_id=...8aba&response_type=code&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&scope=read Then paste the access token here: ...033d Mastodon: Request to endpoint "/oauth/token" using method "POST". Parameters: {'redirect_uri': 'urn:ietf:wg:oauth:2.0:oob', 'code': '...033d', 'grant_type': 'authorization_code', 'client_id': '...8aba', 'client_secret': '...b138', 'scope': 'read'} Headers: None Files: {} Mastodon: Response received with code 401. response headers: {... 'WWW-Authenticate': 'Bearer realm="Doorkeeper", error="invalid_grant", error_description="The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client."' ...} Response text content: {"error":"invalid_grant","error_description":"The provided authorization grant is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client."}I started wondering: is this because of the
scopeparameter? I was missing thescopeparameter in my call tocreate_app. I made that change but saw no difference.I then thought perhaps the problem is the missing
redirect_urisinauth_request_urlandredirect_uriinlog_in. I added them both but saw no difference.I then thought perhaps something about scopes was wrong so I removed
scopes,redirect_urisandredirect_urifrom the various calls but saw no difference.Sadly, the Mastodon.py documentation and the Doorkeeper documentation it refers to is very sparse indeed.
Mastodon.pydoesn’t tell me how to really do OAuth and Doorkeeper only tells me how to do it with a password (Resource Owner Password Credentials) and not how to use Client Credentials.It is all quite frustrating.
And most disturbing of all: it continues to work for octodon.social but doesn’t work for any of the other instances I have tried, e.g. social.nasqueron.org.
As I said, it is all quite frustrating.
As expected, switching the entire thing to password credentials “works”:
mastodon = Mastodon( client_id = client_secret, api_base_url = url) print("We need your credentials just this once to log in.") sys.stdout.write("Email: ") sys.stdout.flush() email = sys.stdin.readline().rstrip() sys.stdout.write("Password: ") sys.stdout.flush() password = sys.stdin.readline().rstrip() mastodon.log_in( username = email, password = password, to_file = user_secret, scopes=scopes)The result:
The word of the day is “frustrating”.
– Alex Schroeder 2018-05-13 19:23 UTC