Add documentation for new OAuth 2.0 features added in 4.3.0

This commit is contained in:
Emelia Smith 2024-05-15 20:17:19 +02:00
parent 94a7463adb
commit 1b3b46d15e
No known key found for this signature in database
7 changed files with 317 additions and 82 deletions

View File

@ -35,9 +35,15 @@ https://mastodon.example/oauth/authorize
Note the following:
* `client_id` was obtained when registering our application.
* `scope` must be a subset of our registered app's registered scopes. It is a good idea to only request what you need. See [OAuth Scopes]({{< relref "api/oauth-scopes" >}}) for more information.
* `redirect_uri` is one of the URIs we registered with our app. We are still using "out of band" for this example, which means we will have to manually copy and paste the resulting code, but if you registered your application with a URI that you control, then the code will be returned as a query parameter `code` and can be logged by your request handler. See the response section of the API method documentation for more information on this.
- `client_id` was obtained when registering our application.
- `scope` must be a subset of our registered app's registered scopes. It is a good idea to only request what you need. See [OAuth Scopes]({{< relref "api/oauth-scopes" >}}) for more information.
- `redirect_uri` is one of the URIs we registered with our app.
We are still using "out of band" for this example, which means we will have to manually copy and paste the resulting code, but if you registered your application with a URI that you control, then the code will be returned as a query parameter `code` by your request handler for the redirect URI. See the response section of the API method documentation for more information on this.
{{< hint style="warning" >}}
Treat the `code` query parameter as if it were a password, you should ensure that it is not logged in request logs.
{{< /hint >}}
### Obtain the token {#token}
@ -56,12 +62,20 @@ curl -X POST \
Note the following:
* `client_id` and `client_secret` were provided in the response text when you registered your application.
* `redirect_uri` must be one of the URIs defined when registering the application.
* We are requesting a `grant_type` of `authorization_code`, which still defaults to giving us the `read` scope. However, while authorizing our user, we requested a certain `scope` -- pass the exact same value here.
* The `code` can only be used once. If you need to obtain a new token, you will need to have the user authorize again by repeating the above [Authorize the user]({{< relref "client/authorized#authorize-the-user" >}}) step.
- `client_id` and `client_secret` were provided in the response text when you registered your application.
- `redirect_uri` must be one of the URIs defined when registering the application.
- We are requesting a `grant_type` of `authorization_code`, which still defaults to giving us the `read` scope. However, while authorizing our user, we requested a certain `scope` -- pass the exact same value here.
- The `code` can only be used once. If you need to obtain a new token, you will need to have the user authorize again by repeating the above [Authorize the user]({{< relref "client/authorized#authorize-the-user" >}}) step.
The response of this method is a [Token]({{< relref "entities/token" >}}) entity. We will need the `access_token` value. Once you have the access token, save it in your local cache. To use it in requests, add the HTTP header `Authorization: Bearer ...` to any API call that requires OAuth (i.e., one that is not publicly accessible). Let's verify that our obtained credentials are working by calling [GET /api/v1/accounts/verify_credentials]({{< relref "methods/accounts#verify_credentials" >}}):
The response of this method is a [Token]({{< relref "entities/token" >}}) entity. We will need the `access_token` value. Once you have the access token, save it in your local cache.
{{< hint style="warning" >}}
Treat the `access_token` as if it were a password. We recommend you encrypt this value when storing in your cache, to prevent accidental credential exposure.
{{< /hint >}}
To use it in requests, add the HTTP header `Authorization: Bearer <access_token>` to any API call that requires OAuth (i.e., one that is not publicly accessible).
Let's verify that our obtained credentials are working by calling [GET /api/v1/accounts/verify_credentials]({{< relref "methods/accounts#verify_credentials" >}}):
```bash
curl \
@ -77,48 +91,47 @@ With our OAuth token for the authorized user, we can now perform any action as t
### Publish and delete statuses {#statuses}
* See [POST /api/v1/statuses]({{< relref "methods/statuses#create" >}}) for how to create statuses.
* See [/api/v1/media]({{< relref "methods/media" >}}) for creating media attachments.
* See [/api/v1/scheduled_statuses]({{< relref "methods/scheduled_statuses" >}}) for managing scheduled statuses.
- See [POST /api/v1/statuses]({{< relref "methods/statuses#create" >}}) for how to create statuses.
- See [/api/v1/media]({{< relref "methods/media" >}}) for creating media attachments.
- See [/api/v1/scheduled_statuses]({{< relref "methods/scheduled_statuses" >}}) for managing scheduled statuses.
### Interact with timelines {#timelines}
* See [/api/v1/timelines]({{< relref "methods/timelines" >}}) for accessing timelines.
* See [/api/v1/markers]({{< relref "methods/markers" >}}) for saving and loading positions in timelines.
* See [/api/v1/statuses]({{< relref "methods/statuses" >}}) for performing actions on statuses.
* See [/api/v1/polls]({{< relref "methods/polls" >}}) for viewing and voting on polls.
* See [/api/v1/lists]({{< relref "methods/lists" >}}) for obtaining list IDs to use with [GET /api/v1/timelines/list/:list_id]({{< relref "methods/timelines#list" >}}).
* See [/api/v1/conversations]({{< relref "methods/conversations" >}}) for obtaining direct conversations.
* See [/api/v1/favourites]({{< relref "methods/favourites" >}}) for listing favourites.
* See [/api/v1/bookmarks]({{< relref "methods/bookmarks" >}}) for listing bookmarks.
- See [/api/v1/timelines]({{< relref "methods/timelines" >}}) for accessing timelines.
- See [/api/v1/markers]({{< relref "methods/markers" >}}) for saving and loading positions in timelines.
- See [/api/v1/statuses]({{< relref "methods/statuses" >}}) for performing actions on statuses.
- See [/api/v1/polls]({{< relref "methods/polls" >}}) for viewing and voting on polls.
- See [/api/v1/lists]({{< relref "methods/lists" >}}) for obtaining list IDs to use with [GET /api/v1/timelines/list/:list_id]({{< relref "methods/timelines#list" >}}).
- See [/api/v1/conversations]({{< relref "methods/conversations" >}}) for obtaining direct conversations.
- See [/api/v1/favourites]({{< relref "methods/favourites" >}}) for listing favourites.
- See [/api/v1/bookmarks]({{< relref "methods/bookmarks" >}}) for listing bookmarks.
### Interact with other users {#accounts}
* See [/api/v1/accounts]({{< relref "methods/accounts" >}}) for performing actions on other users.
* See [/api/v1/follow_requests]({{< relref "methods/follow_requests" >}}) for handling follow requests.
* See [/api/v1/mutes]({{< relref "methods/mutes" >}}) for listing mutes.
* See [/api/v1/blocks]({{< relref "methods/blocks" >}}) for listing blocks.
- See [/api/v1/accounts]({{< relref "methods/accounts" >}}) for performing actions on other users.
- See [/api/v1/follow_requests]({{< relref "methods/follow_requests" >}}) for handling follow requests.
- See [/api/v1/mutes]({{< relref "methods/mutes" >}}) for listing mutes.
- See [/api/v1/blocks]({{< relref "methods/blocks" >}}) for listing blocks.
### Receive notifications {#notifications}
* See [/api/v1/notifications]({{< relref "methods/notifications" >}}) for managing a user's notifications.
* See [/api/v1/push]({{< relref "methods/push" >}}) for subscribing to push notifications.
- See [/api/v1/notifications]({{< relref "methods/notifications" >}}) for managing a user's notifications.
- See [/api/v1/push]({{< relref "methods/push" >}}) for subscribing to push notifications.
### Discovery features {#discovery}
* See [/api/v2/search]({{< relref "methods/search#v2" >}}) for querying resources.
* See [/api/v1/suggestions]({{< relref "methods/suggestions" >}}) for suggested accounts to follow.
- See [/api/v2/search]({{< relref "methods/search#v2" >}}) for querying resources.
- See [/api/v1/suggestions]({{< relref "methods/suggestions" >}}) for suggested accounts to follow.
### User safety features {#safety}
* See [/api/v1/filters]({{< relref "methods/filters" >}}) for managing filtered keywords.
* See [/api/v1/domain_blocks]({{< relref "methods/domain_blocks" >}}) for managing blocked domains.
* See [/api/v1/reports]({{< relref "methods/reports" >}}) for creating reports.
* See [/api/v1/admin]({{< relref "methods/admin" >}}) for moderator actions.
- See [/api/v1/filters]({{< relref "methods/filters" >}}) for managing filtered keywords.
- See [/api/v1/domain_blocks]({{< relref "methods/domain_blocks" >}}) for managing blocked domains.
- See [/api/v1/reports]({{< relref "methods/reports" >}}) for creating reports.
- See [/api/v1/admin]({{< relref "methods/admin" >}}) for moderator actions.
### Manage account info {#manage}
* See [/api/v1/endorsements]({{< relref "methods/endorsements" >}}) for managing a user profile's featured accounts.
* See [/api/v1/featured_tags]({{< relref "methods/featured_tags" >}}) for managing a user profile's featured hashtags.
* See [/api/v1/preferences]({{< relref "methods/preferences" >}}) for reading user preferences.
- See [/api/v1/endorsements]({{< relref "methods/endorsements" >}}) for managing a user profile's featured accounts.
- See [/api/v1/featured_tags]({{< relref "methods/featured_tags" >}}) for managing a user profile's featured hashtags.
- See [/api/v1/preferences]({{< relref "methods/preferences" >}}) for reading user preferences.

View File

@ -28,10 +28,18 @@ curl -X POST \
In the above example, we specify the client name and website, which will be shown on statuses if applicable. But more importantly, note the following two parameters:
* `redirect_uris` has been set to the "out of band" token generation, which means that any generated tokens will have to be copied and pasted manually. The parameter is called `redirect_uris` because it is possible to define more than one redirect URI, but when generating the token, we will need to provide a URI that is included within this list.
* `scopes` allow us to define what permissions we can request later. However, the requested scope later can be a subset of these registered scopes. See [OAuth Scopes]({{< relref "api/oauth-scopes" >}}) for more information.
- `redirect_uris` has been set to the "out of band" token generation, which means that any generated tokens will have to be copied and pasted manually. The parameter is called `redirect_uris` because it is possible to define more than one redirect URI, but when generating the token, we will need to provide a URI that is included within this list.
- `scopes` allow us to define what permissions we can request later. However, the requested scope later can be a subset of these registered scopes. See [OAuth Scopes]({{< relref "api/oauth-scopes" >}}) for more information.
We should see an Application entity returned, but for now, we only care about client_id and client_secret. These values will be used to generate access tokens, so they should be cached for later use. See [POST /api/v1/apps]({{< relref "methods/apps#create" >}}) for more details on registering applications.
{{< hint style="warning" >}}
As of Mastodon 4.3.0, you can make a request to [`/.well-known/oauth-authorization-server`]({{< relref "spec/oauth#authorization-server-metadata" >}}) to discover what `scopes` the server supports. In older versions of Mastodon, this endpoint will be a 404, so you should decide a "minimum version supported" for the Mastodon server that your application is interacting with.
{{< /hint >}}
We should see an [Application]({{< relref "entities/application" >}}) entity returned, but for now, we only care about `client_id` and `client_secret`. These values will be used to generate access tokens, so they should be cached for later use. See [POST /api/v1/apps]({{< relref "methods/apps#create" >}}) for more details on registering applications.
{{< hint style="warning" >}}
Treat the `client_id` and `client_secret` properties as if they are passwords. We recommend you encrypt these when storing in your cache, to prevent accidental credential exposure.
{{< /hint >}}
## Example authentication code flow {#flow}
@ -48,11 +56,19 @@ curl -X POST \
Note the following:
* `client_id` and `client_secret` were provided in the response text when you registered your application.
* `redirect_uri` must be one of the URIs defined when registering the application.
* We are requesting a `grant_type` of `client_credentials`, which defaults to giving us the `read` scope.
- `client_id` and `client_secret` were provided in the response text when you registered your application.
- `redirect_uri` must be one of the URIs defined when registering the application.
- We are requesting a `grant_type` of `client_credentials`, which defaults to giving us the `read` scope.
The response of this method is a [Token]({{< relref "entities/token" >}}) entity. We will need the `access_token` value. Once you have the access token, save it in your local cache. To use it in requests, add the HTTP header `Authorization: Bearer ...` to any API call that requires OAuth (i.e., one that is not publicly accessible). Let's verify that our obtained credentials are working by calling [GET /api/v1/apps/verify_credentials]({{< relref "methods/apps#verify_credentials" >}}):
The response of this method is a [Token]({{< relref "entities/token" >}}) entity. We will need the `access_token` value. Once you have the access token, save it in your local cache.
{{< hint style="warning" >}}
Treat the `access_token` as if it were a password. We recommend you encrypt this value when storing in your cache, to prevent accidental credential exposure.
{{< /hint >}}
To use it in requests, add the HTTP header `Authorization: Bearer <access_token>` to any API call that requires OAuth (i.e., one that is not publicly accessible).
Let's verify that our obtained credentials are working by calling [GET /api/v1/apps/verify_credentials]({{< relref "methods/apps#verify_credentials" >}}):
```bash
curl \
@ -60,9 +76,8 @@ curl \
https://mastodon.example/api/v1/apps/verify_credentials
```
If we've obtained our token and formatted our request correctly, we should see our details returned to us as an [Application]({{< relref "entities/application" >}}) entity.
If we've obtained our token and formatted our request correctly, we should see our details returned to us as an [Application]({{< relref "entities/application" >}}) entity (without the `client_secret` property).
## What we can do with authentication {#methods}
With our authenticated client application, we can view relations of an account with [GET /api/v1/accounts/:id/following]({{< relref "methods/accounts#following" >}}) and [GET /api/v1/accounts/:id/followers]({{< relref "methods/accounts#followers" >}}). Also, some instances may require authentication for methods that would otherwise be public, so if you encountered any authentication errors while playing around with public methods, then those methods should now work.

View File

@ -7,7 +7,11 @@ menu:
parent: dev
---
Mastodon is a Ruby on Rails application with a React.js front-end. It follows standard practices of those frameworks, so if you are already familiar with Rails or React.js, you will not find any surprises here.
<style>
#TableOfContents {display: none}
</style>
Mastodon is a Ruby on Rails application with a React.js front-end. It follows standard practices of those frameworks, so if you are already familiar with Rails or React.js, you will not find any surprises here.
The best way of working with Mastodon in a development environment is installing all the dependencies on your system, rather than using Docker or Vagrant. You need Ruby, Node.js, PostgreSQL and Redis, which is a pretty standard set of dependencies for Rails applications.
@ -19,11 +23,10 @@ An “environment” is a set of configuration values intended for a specific us
The default value of `RAILS_ENV` is `development`, so you dont need to set anything extra to run Mastodon in development mode. In fact, all of Mastodons configuration has correct defaults for the development environment, so you do not need an `.env` file unless you need to customize something. Here are some of the different behaviours between the development environment and the production environment:
* Ruby code reloads itself when you change it, which means you dont need to restart the Rails server process to see changes
* All errors you encounter show stack traces in the browser, rather than being hidden behind a generic error page
* Webpack runs continuously and re-compiles JS and CSS assets when you change any of the front-end files, and the pages automatically reload
* Caching is disabled by default
* An admin account with the e-mail `admin@localhost:3000` and password `mastodonadmin` is created automatically during `db:seed`
- Ruby code reloads itself when you change it, which means you dont need to restart the Rails server process to see changes
- All errors you encounter show stack traces in the browser, rather than being hidden behind a generic error page
- Webpack runs continuously and re-compiles JS and CSS assets when you change any of the front-end files, and the pages automatically reload
- Caching is disabled by default
- An admin account with the e-mail `admin@localhost:3000` and password `mastodonadmin` is created automatically during `db:seed`
It should be noted that the Docker configuration distributed with Mastodon is optimized for the production environment, and so is an extremely bad fit for development. The Vagrant configuration, on the other hand, is meant specifically for development and not production use.

View File

@ -16,8 +16,14 @@ aliases: [
```json
{
"name": "test app",
"website": null
"name": "Test Application",
"website": "https://app.example",
"scopes": ["read", "write", "push"],
"redirect_uri": "https://app.example/callback\nhttps://app.example/register",
"redirect_uris": [
"https://app.example/callback",
"https://app.example/register"
]
}
```
@ -38,12 +44,13 @@ aliases: [
0.9.9 - added\
3.5.1 - this property is now nullable
### `client_id` {{%optional%}} {#client_id}
### `client_id` {#client_id}
**Description:** Client ID key, to be used for obtaining OAuth tokens\
**Type:** String\
**Version history:**\
0.9.9 - added
4.3.0 - changed to always be returned
### `client_secret` {{%optional%}} {#client_secret}
@ -52,8 +59,31 @@ aliases: [
**Version history:**\
0.9.9 - added
### `scopes` {#scopes}
**Description:** The scopes for your application. This is the registered `scopes` string split on whitespace.\
**Type:** Array of Strings\
**Version history:**\
4.3.0 - added
### `redirect_uris` {#redirect_uris}
**Description:** The registered redirection URI(s) for your application.\
**Type:** Array of String (URLs or `"urn:ietf:wg:oauth:2.0:oob"` as values)\
**Version history:**\
4.3.0 - added
## Deprecated attributes
### `redirect_uri` {#redirect_uri}
**Description:** The registered redirection URI(s) for your application.\
May contain `\n` characters when multiple redirect URIs are registered.\
**Type:** String\
**Version history:**\
0.0.0 - added\
4.3.0 - deprecated in favour of [`redirect_uris`]({{< relref "entities/Application#redirect_uris" >}}), since the value of this property is not a well-formed URI when multiple redirect URIs are registered
### `vapid_key` {#vapid_key}
**Description:** Used for Push Streaming API. Returned with [POST /api/v1/apps]({{< relref "methods/apps#create" >}}). Equivalent to [WebPushSubscription#server_key]({{< relref "entities/WebPushSubscription#server_key" >}}) and [Instance#vapid_public_key]({{< relref "entities/Instance#vapid_public_key" >}})\

View File

@ -7,10 +7,7 @@ menu:
name: apps
parent: methods
identifier: methods-apps
aliases: [
"/methods/apps",
"/api/methods/apps",
]
aliases: ["/methods/apps", "/api/methods/apps"]
---
<style>
@ -30,17 +27,34 @@ Create a new application to obtain OAuth2 credentials.
**Version history:**\
0.0.0 - added\
2.7.2 - now returns `vapid_key`\
4.3.0 - deprecated `vapid_key`, please see [api/v2/instance]({{< relref "methods/Instance#v2">}})
4.3.0 - deprecated `vapid_key`, please see [api/v2/instance]({{< relref "methods/Instance#v2">}})\
4.3.0 - added support for multiple `redirect_uris` in Form data parameters\
4.3.0 - added `redirect_uris` response property\
4.3.0 - deprecated `redirect_uri` response property, since this can be a non-URI if multiple `redirect_uris` are registered
#### Request
Example request:
```
POST /api/v1/apps HTTP/1.1
Content-Type: application/json
{
"client_name": "Test Application",
"redirect_uris": ["https://app.example/callback", "https://app.example/register"],
"scopes": "read write push",
"website": "https://app.example"
}
```
##### Form data parameters
client_name
: {{<required>}} String. A name for your application
redirect_uris
: {{<required>}} String. Where the user should be redirected after authorization. To display the authorization code to the user instead of redirecting to a web page, use `urn:ietf:wg:oauth:2.0:oob` in this parameter.
: {{<required>}} String or Array of Strings. Where the user should be redirected after authorization. To display the authorization code to the user instead of redirecting to a web page, use `urn:ietf:wg:oauth:2.0:oob` in this parameter.
scopes
: String. Space separated list of scopes. If none is provided, defaults to `read`. See [OAuth Scopes]({{< relref "api/oauth-scopes" >}}) for a list of possible scopes.
@ -54,17 +68,45 @@ website
Store the `client_id` and `client_secret` in your cache, as these will be used to obtain OAuth tokens.
{{< hint style="warning" >}}
Treat the `client_id` and `client_secret` properties as if they are passwords. We recommend you encrypt these when storing in your cache, to prevent credential exposure.
{{< /hint >}}
```json
{
"id": "563419",
"name": "test app",
"website": null,
"name": "Test Application",
"website": "https://app.example",
"scopes": ["read", "write", "push"],
"redirect_uri": "urn:ietf:wg:oauth:2.0:oob",
"redirect_uris": ["urn:ietf:wg:oauth:2.0:oob"],
"client_id": "TWhM-tNSuncnqN7DBJmoyeLnk6K3iJJ71KKXxgL1hPM",
"client_secret": "ZEaFUFmF0umgBX1qKJDjaU99Q31lDkOU8NutzTOoliw"
}
```
Or with multiple redirect URIs:
```json
{
"id": "563419",
"name": "Test Application",
"website": "https://app.example",
"scopes": ["read", "write", "push"],
"redirect_uri": "https://app.example/callback\nhttps://app.example/register",
"redirect_uris": [
"https://app.example/callback",
"https://app.example/register"
],
"client_id": "TWhM-tNSuncnqN7DBJmoyeLnk6K3iJJ71KKXxgL1hPM",
"client_secret": "ZEaFUFmF0umgBX1qKJDjaU99Q31lDkOU8NutzTOoliw"
}
```
{{< hint style="info" >}}
The `redirect_uri` property in the above examples is considered deprecated as of 4.3.0 and should not be used, instead use the `redirect_uris` property.
{{< /hint >}}
##### 422: Unprocessable entity
If a required parameter is missing or improperly formatted, the request will fail.
@ -85,19 +127,21 @@ GET /api/v1/apps/verify_credentials HTTP/1.1
Confirm that the app's OAuth2 credentials work.
**Returns:** [Application]({{< relref "entities/application" >}}), but without `client_id` or `client_secret`\
**OAuth level:** App token + `read`\
**Returns:** [Application]({{< relref "entities/application" >}}), but without `client_secret`\
**OAuth level:** App token\
**Version history:**\
2.0.0 - added\
2.7.2 - now returns `vapid_key`\
4.3.0 - deprecated `vapid_key`, please see [api/v2/instance]({{< relref "methods/Instance#v2">}})
4.3.0 - deprecated `vapid_key`, please see [api/v2/instance]({{< relref "methods/Instance#v2">}})\
4.3.0 - removed the need to have `read` scope to access this API, now any valid App token can be used
4.3.0 - added `client_id`, `scopes` and `redirect_uris` properties
#### Request
##### Headers
Authorization
: {{<required>}} Provide this header with `Bearer <app token>` to gain authorized access to this API method.
: {{<required>}} Provide this header with `Bearer <app token>` to gain authorized access to this API method. `<app token>` may be either a `client_credential` or `access_token` returned from [`/oauth/token`]({{< relref "methods/oauth#token" >}})
#### Response
@ -107,8 +151,14 @@ If the Authorization header was provided with a valid token, you should see your
```json
{
"name": "test app",
"website": null
"name": "Test Application",
"website": "https://app.example",
"scopes": ["read", "write", "push"],
"redirect_uris": [
"https://app.example/callback",
"https://app.example/register"
],
"client_id": "TWhM-tNSuncnqN7DBJmoyeLnk6K3iJJ71KKXxgL1hPM"
}
```

View File

@ -1,5 +1,5 @@
---
title: oauth API methods
title: OAuth API methods
description: Generate and manage OAuth tokens.
menu:
docs:
@ -7,11 +7,7 @@ menu:
name: oauth
parent: methods-apps
identifier: methods-oauth
aliases: [
"/methods/oauth",
"/api/methods/oauth",
"/methods/apps/oauth",
]
aliases: ["/methods/oauth", "/api/methods/oauth", "/methods/apps/oauth"]
---
<style>
@ -34,6 +30,7 @@ Displays an authorization form to the user. If approved, it will create and retu
3.5.0 - added `lang`
#### Request
##### Query parameters
response_type
@ -55,10 +52,15 @@ lang
: String. The ISO 639-1 two-letter language code to use while rendering the authorization form.
#### Response
##### 200: OK
The authorization code will be returned as a query parameter named `code`.
{{< hint style="warning" >}}
Treat the `code` query parameter as if it were a password, you should ensure that it is not logged in request logs.
{{< /hint >}}
```http
redirect_uri?code=qDFUEaYrRK5c-HNmTCJbAzazwLRInJ7VHFat0wcMgCU
```
@ -90,6 +92,7 @@ Obtain an access token, to be used during API calls that are not public.
0.1.0 - added
#### Request
##### Form data parameters
grant_type
@ -111,10 +114,17 @@ scope
: String. List of requested OAuth scopes, separated by spaces (or by pluses, if using query parameters). If `code` was provided, then this must be equal to the `scope` requested from the user. Otherwise, it must be a subset of `scopes` declared during app registration. If not provided, defaults to `read`.
#### Response
##### 200: OK
Store this access_token for later use with auth-required methods. The token should be passed as an HTTP `Authorization` header when making API calls, with the value `Bearer access_token`
{{< hint style="warning" >}}
Treat the `access_token` as if it were a password. We recommend you encrypt this value when storing in your cache, to prevent credential exposure.\
\
Additionally, you should ensure that the `code` parameter is not logged.
{{< /hint >}}
```json
{
"access_token": "ZA-Yj3aBD8U8Cm7lKUp-lm9O9BmDgdhHzDeqsY8tlL0",
@ -159,9 +169,10 @@ Revoke an access token to make it no longer valid for use.
**Returns:** Empty\
**OAuth:** Public\
**Version history:**\
x.x.x - added
0.1.0 - added
#### Request
##### Form data parameters
client_id
@ -174,6 +185,7 @@ token
: {{<required>}} String. The previously obtained token, to be invalidated.
#### Response
##### 200: OK
If you own the provided token, the API call will provide an empty response. This operation is idempotent, so calling this API multiple times will still return OK.
@ -195,6 +207,110 @@ If you provide a token you do not own, or no token at all, the API call will ret
---
## Discover OAuth Server Configuration {#authorization-server-metadata}
```http
GET /.well-known/oauth-authorization-server HTTP/1.1
```
Returns the OAuth 2 Authorization Server Metadata for the Mastodon server, as defined by [RFC 8414](https://datatracker.ietf.org/doc/html/rfc8414#section-3.2).
We include the additional non-standard property of `app_registration_endpoint` which refers to the [POST /api/v1/apps]({{% relref ref="methods/apps#create" %}}) endpoint, since we don't currently support the standard `registration_endpoint` endpoint for [Dynamic Client Registration](https://oauth.net/2/dynamic-client-registration/).
The properties exposed by this endpoint can help you better integrate with the Mastodon API, such as allowing for negotiation of `scopes` across different versions of Mastodon.
{{< hint style="info" >}}
**Example:** You want to use the `read:me` scope, but also want to support older Mastodon servers that don't have that scope and would need `read:accounts` instead. You could discover whether a server supports that scope by making a request this endpoint.
{{< /hint >}}
**Returns:** JSON as per the above description\
**OAuth:** Public\
**Version history:**\
4.3.0 - added
#### Response
##### 200: OK
```json
{
"issuer": "https://social.example/",
"service_documentation": "https://docs.joinmastodon.org/",
"authorization_endpoint": "https://social.example/oauth/authorize",
"token_endpoint": "https://social.example/oauth/token",
"app_registration_endpoint": "https://social.example/api/v1/apps",
"revocation_endpoint": "https://social.example/oauth/revoke",
"scopes_supported": [
"read",
"write",
"write:accounts",
"write:blocks",
"write:bookmarks",
"write:conversations",
"write:favourites",
"write:filters",
"write:follows",
"write:lists",
"write:media",
"write:mutes",
"write:notifications",
"write:reports",
"write:statuses",
"read:accounts",
"read:blocks",
"read:bookmarks",
"read:favourites",
"read:filters",
"read:follows",
"read:lists",
"read:mutes",
"read:notifications",
"read:search",
"read:statuses",
"follow",
"push",
"admin:read",
"admin:read:accounts",
"admin:read:reports",
"admin:read:domain_allows",
"admin:read:domain_blocks",
"admin:read:ip_blocks",
"admin:read:email_domain_blocks",
"admin:read:canonical_email_blocks",
"admin:write",
"admin:write:accounts",
"admin:write:reports",
"admin:write:domain_allows",
"admin:write:domain_blocks",
"admin:write:ip_blocks",
"admin:write:email_domain_blocks",
"admin:write:canonical_email_blocks",
"crypto"
],
"response_types_supported": ["code"],
"response_modes_supported": ["query", "fragment", "form_post"],
"grant_types_supported": [
"authorization_code",
"password",
"client_credentials"
],
"token_endpoint_auth_methods_supported": [
"client_secret_basic",
"client_secret_post"
]
}
```
##### Older Mastodon Versions 404: Not Found
On Mastodon versions before 4.3.0, requesting this endpoint will result in a `404 Not Found` error.
This is a good indication that the server is running Mastodon older than 4.3.0 and cannot use features added in 4.3.0 and later versions. Instead, you will need to "guess" what that server supports, instead of discovering supported OAuth 2 endpoints, grant flows & scopes dynamically.
You may want to fallback to the [Instance Metadata endpoint]({{% relref ref="methods/instance#v2" %}}) to try to discover what Mastodon version the server is running by parsing the `version` field, however, this is very brittle and not recommended.
---
## See also
{{< page-relref ref="methods/apps#create" caption="POST /api/v1/apps" >}}
@ -203,4 +319,4 @@ If you provide a token you do not own, or no token at all, the API call will ret
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/oauth/authorized_applications_controller.rb" caption="app/controllers/oauth/authorized_applications_controller.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/oauth/tokens_controller.rb" caption="app/controllers/oauth/tokens_controller.rb" >}}
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/oauth/tokens_controller.rb" caption="app/controllers/oauth/tokens_controller.rb" >}}

View File

@ -19,6 +19,15 @@ The following descriptions are taken from the [Doorkeeper documentation](https:/
{{< caption-link url="https://github.com/mastodon/mastodon/blob/main/config/initializers/doorkeeper.rb" caption="Doorkeeper config initializer" >}}
### Authorization Server Metadata endpoint (RFC 8414) {#authorization-server-metadata}
[GET /.well-known/oauth-authorization-server]({{% relref "methods/oauth#authorization-server-metadata" %}})
**Version history:**\
4.3.0 - added
Returns a JSON document representing the configuration of the OAuth 2 server in Mastodon. Information includes `scopes` available for use when [registering Applications]({{% relref "methods/apps#create" %}}) or requesting [access tokens]({{% relref "methods/oauth#token" %}}), `grant_types_supported` which are can be used when requesting access tokens, and various endpoints for interacting with the Mastodon OAuth server, such as `authorization_endpoint` and `token_endpoint`.
### Authorization endpoint (RFC 6749 Section 3.1) {#authorization}
[GET /oauth/authorize]({{% relref "methods/oauth#authorize" %}})
@ -34,12 +43,12 @@ Obtain an access token. Mastodon supports the following OAuth 2 flows:
Authorization code flow
: For end-users
Password grant flow
: For bots and other single-user applications
Client credentials flow
: For applications that do not act on behalf of users
Password grant flow
: For bots and other single-user applications. Usage [not recommended](https://datatracker.ietf.org/doc/html/draft-ietf-oauth-security-topics#name-resource-owner-password-cre) by the OAuth 2 Specification authors due to security concerns. This grant flow may be removed in future versions of Mastodon.
### Token revocation endpoint (RFC 7009 Section 2) {#revoke}
[POST /oauth/revoke]({{% relref "methods/oauth#revoke" %}})
@ -48,6 +57,5 @@ Post here with client credentials to revoke an access token.
## Common gotchas {#gotchas}
* When registering an application using Mastodon's REST API, there is a `scopes` parameter. When interfacing with OAuth endpoints, you must use the `scope` parameter instead, and this parameter's value must be a subset of the `scopes` registered with the app. You cannot include anything that wasn't in the original set.
* When registering an application using Mastodon's REST API, there is a `redirect_uris` parameter. When interfacing with OAuth endpoints, you must use the `redirect_uri` parameter instead, and this parameter's value must be one of the `redirect_uris` registered with the app.
- When registering an application using Mastodon's REST API, there is a `scopes` parameter. When interfacing with OAuth endpoints, you must use the `scope` parameter instead, and this parameter's value must be a subset of the `scopes` registered with the app. You cannot include anything that wasn't in the original set.
- When registering an application using Mastodon's REST API, there is a `redirect_uris` parameter. When interfacing with OAuth endpoints, you must use the `redirect_uri` parameter instead, and this parameter's value must be one of the `redirect_uris` registered with the app.