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.

BASH 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 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:

BASH 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 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:

BASH 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 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

  1. User providers their Mastodon instance's domain name
  2. 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 and client_secret
  3. Redirect the User to their Mastodon instance, using a URl which contains the client_id & callback URl
  4. User logs in to their Mastodon instance
  5. 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
  6. Your service reads the User's domain name and authorisation code
  7. Your service exchanges those details for a Bearer token
  8. 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?


Share this post on…

  • Mastodon
  • Facebook
  • LinkedIn
  • BlueSky
  • Threads
  • Reddit
  • HackerNews
  • Lobsters
  • WhatsApp
  • Telegram

One thought on “Creating a generic "Log-in with Mastodon" service”

What are your reckons?

All comments are moderated and may not be published immediately. Your email address will not be published.

Allowed HTML: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong> <p> <pre> <br> <img src="" alt="" title="" srcset="">