--- title: OAuth API methods description: Generate and manage OAuth tokens. menu: docs: weight: 10 name: oauth parent: methods-apps identifier: methods-oauth aliases: ["/methods/oauth", "/api/methods/oauth", "/methods/apps/oauth"] --- ## Authorize a user {#authorize} ```http GET /oauth/authorize HTTP/1.1 ``` Displays an authorization form to the user. If approved, it will create and return an authorization code, then redirect to the desired `redirect_uri`, or show the authorization code if `urn:ietf:wg:oauth:2.0:oob` was requested. The authorization code can be used while requesting a token to obtain access to user-level methods. **Returns:** String (URL) or HTML response\ **OAuth:** Public\ **Version history:**\ 0.1.0 - added\ 2.6.0 - added `force_login`\ 3.5.0 - added `lang` 4.3.0 - added support for PKCE parameters #### Request ##### Query parameters response_type : {{}} String. Should be set equal to `code`. client_id : {{}} String. The client ID, obtained during app registration. redirect_uri : {{}} String. Set a URI to redirect the user to. If this parameter is set to `urn:ietf:wg:oauth:2.0:oob` then the authorization code will be shown instead. Must match one of the `redirect_uris` declared during app registration. scope : String. List of requested [OAuth scopes]({{< relref "api/oauth-scopes" >}}), separated by spaces (or by pluses, if using query parameters). Must be a subset of `scopes` declared during app registration. If not provided, defaults to `read`. state : String. Arbitrary value to passthrough to your server when the user authorizes or rejects the authorization request. code_challenge : String. The [PKCE code challenge]({{< relref "spec/oauth#pkce" >}}) for the authorization request. code_challenge_method : String. Must be `S256`, as this is the only code challenge method that is supported by Mastodon for PKCE. force_login : Boolean. Forces the user to re-login, which is necessary for authorizing with multiple accounts from the same instance. 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 ``` If the state parameter was used, then this will also be present in the URI when the client is redirected. ```http redirect_uri?code=qDFUEaYrRK5c-HNmTCJbAzazwLRInJ7VHFat0wcMgCU&state=example ``` ##### 400: Client error If the authorization code is incorrect or has been used already, the request will fail. ```json { "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." } ``` --- ## Obtain a token {#token} ```http POST /oauth/token HTTP/1.1 ``` Obtain an access token, to be used during API calls that are not public. **Returns:** [Token]({{< relref "entities/token" >}})\ **OAuth:** Public\ **Version history:**\ 0.1.0 - added 4.3.0 - added support for PKCE parameter #### Request ##### Form data parameters grant_type : {{}} String. Set equal to `authorization_code` if `code` is provided in order to gain user-level access. Otherwise, set equal to `client_credentials` to obtain app-level access only. code : {{}} String. A user authorization code, obtained from the redirect after an [Authorization request](#authorize) is approved. May alternatively be displayed to the user if `urn:ietf:wg:oauth:2.0:oob` is used as the `redirect_uri`. client_id : {{}} String. The client ID, obtained during app registration. client_secret : {{}} String. The client secret, obtained during app registration. redirect_uri : {{}} String. Must match the `redirect_uri` used during the [Authorization request](#authorize). code_verifier : String. Required if [PKCE]({{< relref "spec/oauth#pkce" >}}) is used during the authorization request. This is the code verifier which was used to create the `code_challenge` using the `code_challenge_method` for the authorization request. scope : String. When `grant_type` is set to `client_credentials`, the list of requested OAuth scopes, separated by spaces (or pluses, if using query parameters). Must be a subset of the scopes requested at the time the application was created. If omitted, it defaults to `read`. Has no effect when `grant_type` is `authorization_code`. #### Response ##### 200: OK Store this `access_token` for later use with methods that require authentication. The token should be passed as an HTTP `Authorization` header when making API calls, with the value `Bearer ` {{< 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", "token_type": "Bearer", "scope": "read write follow push", "created_at": 1573979017 } ``` ##### 400: Client error If you try to request a scope that was not included when registering the app, the request will fail. ```json { "error": "invalid_scope", "error_description": "The requested scope is invalid, unknown, or malformed." } ``` ##### 401: Unauthorized If client_id and client_secret do not match or are invalid, the request will fail. ```json { "error": "invalid_client", "error_description": "Client authentication failed due to unknown client, no client authentication included, or unsupported authentication method." } ``` --- ## Revoke a token {#revoke} ```http POST /oauth/revoke HTTP/1.1 ``` Revoke an access token to make it no longer valid for use. **Returns:** Empty\ **OAuth:** Public\ **Version history:**\ 0.1.0 - added #### Request ##### Form data parameters client_id : {{}} String. The client ID, obtained during app registration. client_secret : {{}} String. The client secret, obtained during app registration. token : {{}} 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. ```json {} ``` ##### 403: Forbidden If you provide a token you do not own, or no token at all, the API call will return a 403 error. ```json { "error": "unauthorized_client", "error_description": "You are not authorized to revoke this token" } ``` --- ## 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 `profile` 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 to 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", "profile", "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" ], "response_types_supported": ["code"], "response_modes_supported": ["query", "fragment", "form_post"], "code_challenge_methods_supported": [ "S256" ], "grant_types_supported": [ "authorization_code", "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. 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" >}} {{< caption-link url="https://github.com/mastodon/mastodon/blob/main/app/controllers/oauth/authorizations_controller.rb" caption="app/controllers/oauth/authorizations_controller.rb" >}} {{< 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" >}}