Creating a generic "Log-in with Mastodon" service
Let's say you have a website - your_website.tld
- and you want people to log in to it using their Mastodon account.
For a traditional social-media site like Twitter or Facebook, you would create an OAuth app on the service that you want. But there are hundreds of Mastodon servers. So you need to create a new app for each one. That sounds hard, but it isn't. Well… not too hard.
Here's some code adapted from Infosec.press. It's all written using cURL on the command line - so you should be able to adapt it to your preferred programming language.
Register an app on the user's Mastodon instance
Let's assume the user has given you the name of their Mastodon server - example.social
You then send a request for an app to be created on example.social
with your website's details. All it requests is the ability to read a user's details, nothing else.
BASHcurl -X POST \
-F "client_name=Login to your_website.tld" \
-F "redirect_uris=https://your_website.tld/oauth/mastodon?server=example.social&" \
-F "scopes=read:accounts" \
-F "website=https://your_website.tld" \
-A "user-agent/0.1"
https://example.social/api/v1/apps
You can set the User Agent to be anything suitable. Some servers won't work if it is omitted.
If the request was successful, example.social
will send you this JSON in response:
JSON{
"id": "12345",
"name": "Login to your_website.tld",
"website": "https://your_website.tld",
"scopes": [
"read:accounts"
],
"redirect_uris": [
"https://your_website.tld/oauth/mastodon?server=example.social&"
],
"vapid_key": "qwertyuiop-asdfghjkl-zxcvbnm",
"redirect_uri": "https://your_website.tld/oauth/mastodon?server=example.social&",
"client_id": "qw_asdfghjkl_zxcvbnm",
"client_secret": "qwertyuiop1234567890"
}
Save the server's address, the client_id
, and the client_secret
. You will need all three later.
The user logs in to their Mastodon instance
You need to redirect the user to their server so they can log in. You need to construct a Mastodon URl using the data you received back. Don't forget to URl encode the redirect_uri
.
For example, redirect the user to:
https://example.social/oauth/authorize
?client_id=qw_asdfghjkl_zxcvbnm
&scope=read:accounts
&redirect_uri=https://your_website.tld/oauth/mastodon%3Fserver=example.social%26
&response_type=code
When the user visits that URl they can then log in. If they're successful, they'll be redirected back to your server using your specified redirect URI:
https://your_website.tld/oauth/mastodon?server=example.social&code=qazwsxedcrfvtgbyhnujm
Get a Bearer token
Your website has received a GET request with the user's server name and an authorisation code. As per the Mastodon documentation, your app uses that code to request a Bearer token:
BASHcurl -X POST \
-F "client_id=qw_asdfghjkl_zxcvbnm" \
-F "client_secret=qwertyuiop1234567890" \
-F "redirect_uri=https://your_website.tld/oauth/mastodon?server=example.social&" \
-F "grant_type=authorization_code" \
-F "code=qazwsxedcrfvtgbyhnujm" \
-F "scope=read:accounts" \
-A "user-agent/0.1"
https://example.social/oauth/token
If that's worked, the user's server will return a Bearer token like this:
JSON{
"access_token": "abcdefg_123456",
"token_type": "Bearer",
"scope": "read:accounts",
"created_at": 1732916685
}
Get the user's details
Finally(!) you can use that token to verify the user's credentials with the server:
BASHcurl \
-H "Authorization: Bearer abcdefg_123456" \
-A "user-agent/0.1"
https://example.social/api/v1/accounts/verify_credentials
If that works, you'll get back all the user's details. Something like this:
JSON{
"id": "7112",
"username": "Edent",
"acct": "Edent",
"display_name": "Terence Eden",
"url": "https://mastodon.social/@Edent",
"avatar": "https://files.mastodon.social/accounts/avatars/000/007/112/original/37df032a5951b96c.jpg",
...
}
Putting it all together
- User providers their Mastodon instance's domain name
- Your service looks up the domain name in its database
- If there are no results, request to create a new app on the Mastodon instance and save the returned
client_id
andclient_secret
- If there are no results, request to create a new app on the Mastodon instance and save the returned
- Redirect the User to their Mastodon instance, using a URl which contains the
client_id
& callback URl - User logs in to their Mastodon instance
- The User's Mastodon instance redirects the User to your service's callback URl which includes an the instance's domain name and User's authorisation code
- Your service reads the User's domain name and authorisation code
- Your service exchanges those details for a Bearer token
- Your service uses the Bearer token to get the User's account details
Next steps?
This basic code works. For my next trick, can I integrate it into Auth0?
dch :flantifa: :flan_hacker: said on bsd.network:
@Edent thats awesome. This would push me over the edge to set up my own instance.
More comments on Mastodon.