https://<server-url>/v1/<api-endpoint>
Note that:
- All API access must be over HTTPS.
- The URL embeds a version identifier "v1"; future revisions of this API may introduce new version numbers.
- The base URL of the server may be configured on a per-client basis.
Invalid requests will return 4XX responses. Internal failures will return 5XX. Both will include JSON responses describing the error.
Example error:
{
"code": 400, // matches the HTTP status code
"errno": 101, // stable application-level error number
"error": "Bad Request", // string description of error type
"message": "Unknown client"
}
The currently-defined error responses are:
status code | errno | description |
---|---|---|
400 | 101 | unknown client id |
400 | 102 | incorrect client secret |
400 | 103 | redirect_uri doesn't match registered value |
401 | 104 | invalid fxa assertion |
400 | 105 | unknown code |
400 | 106 | incorrect code |
400 | 107 | expired code |
400 | 108 | invalid token |
400 | 109 | invalid request parameter |
400 | 110 | invalid response_type |
401 | 111 | unauthorized |
403 | 112 | forbidden |
415 | 113 | invalid content type |
400 | 114 | invalid scopes |
400 | 115 | expired token |
400 | 116 | not a public client |
400 | 117 | incorrect code_challenge |
400 | 118 | pkce parameters missing |
400 | 119 | stale authentication timestamp |
400 | 120 | mismatch acr value |
400 | 121 | invalid grant_type |
500 | 999 | internal server error |
- GET /v1/authorization
- GET /v1/jwks
- POST /v1/authorization
- POST /v1/token
- POST /v1/destroy
- Clients
- Developers
- POST /v1/verify
- POST /v1/key-data
- GET /v1/client-tokens
- DELETE /v1/client-tokens/:id
This endpoint is for the fxa-content-server to retrieve information about a client to show in its user interface.
id
: Theclient_id
of a client asking for permission.
Example:
curl -v "https://oauth.accounts.firefox.com/v1/client/5901bd09376fadaa"
A valid 200 response will be a JSON blob with the following properties:
name
: A string name of the client.image_uri
: A url to a logo or image that represents the client.redirect_uri
: The url registered to redirect to after successful oauth.trusted
: Whether the client is a trusted internal application.
Example:
{
"name": "Where's My Fox",
"image_uri": "https://mozilla.org/firefox.png",
"redirect_uri": "https://wheres.my.firefox.com/oauth",
"trusted": true
}
Get a list of all registered clients.
Required scope: oauth
Example:
curl -v \
-H "Authorization: Bearer 558f9980ad5a9c279beb52123653967342f702e84d3ab34c7f80427a6a37e2c0" \
"https://oauth.accounts.firefox.com/v1/clients"
A valid 200 response will be a JSON object with a property of clients
,
which contains an array of client objects.
Example:
{
"clients": [
{
"id": "5901bd09376fadaa",
"name": "Example",
"redirect_uri": "https://ex.am.ple/path",
"image_uri": "https://ex.am.ple/logo.png",
"can_grant": false,
"trusted": false
}
]
}
Register a new client (FxA relier).
Required scope: oauth
name
: The name of the client.redirect_uri
: The URI to redirect to after logging in.image_uri
: A URI to an image to show to a user when logging in.trusted
: Whether the client is a trusted internal application.can_grant
: A client needs permission to get implicit grants.
Example:
curl -v \
-X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer 558f9980ad5a9c279beb52123653967342f702e84d3ab34c7f80427a6a37e2c0" \
"https://oauth.accounts.firefox.com/v1/client" \
-d '{
"name": "Example",
"redirect_uri": "https://ex.am.ple/path",
"image_uri": "https://ex.am.ple/logo.png",
"trusted": false,
"can_grant": false
}'
A valid 201 response will be a JSON blob with the following properties:
client_id
: The generated id for this client.client_secret
: The generated secret for this client. NOTE: This is the only time you can get the secret, because we only keep a hashed version.name
: A string name of the client.image_uri
: A url to a logo or image that represents the client.redirect_uri
: The url registered to redirect to after successful oauth.can_grant
: If the client can get implicit grants.trusted
: Whether the client is a trusted internal application.
Example:
{
"client_id": "5901bd09376fadaa",
"client_secret": "4ab433e31ef3a7cf7c20590f047987922b5c9ceb1faff56f0f8164df053dd94c",
"name": "Example",
"redirect_uri": "https://ex.am.ple/path",
"image_uri": "https://ex.am.ple/logo.png",
"can_grant": false,
"trusted": false
}
Update the details of a client. Any parameter not included in the request will stay unchanged.
Required scope: oauth
name
: The name of the client.redirect_uri
: The URI to redirect to after logging in.image_uri
: A URI to an image to show to a user when logging in.trusted
: Whether the client is a trusted internal application.can_grant
: A client needs permission to get implicit grants.
Example:
curl -v \
-X POST \
-H "Content-Type: application/json" \
-H "Authorization: Bearer 558f9980ad5a9c279beb52123653967342f702e84d3ab34c7f80427a6a37e2c0" \
"https://oauth.accounts.firefox.com/v1/client/5901bd09376fadaa" \
-d '{
"name": "Example2",
"redirect_uri": "https://ex.am.ple/path/2",
"image_uri": "https://ex.am.ple/logo2.png",
}'
A valid response will have a 200 status code and empty object {}
.
Delete a client. It will be no more. Zilch. Nada. Nuked from orbit.
Required scope: oauth
Example:
curl -v \
-X DELETE \
-H "Authorization: Bearer 558f9980ad5a9c279beb52123653967342f702e84d3ab34c7f80427a6a37e2c0" \
"https://oauth.accounts.firefox.com/v1/client/5901bd09376fadaa"
A valid response will have a 204 response code and an empty body.
Register an oauth developer.
Required scope: oauth
- None
A valid response will have a 200 status code and a developer object:
{"developerId":"f5b176ab5be5928d01d4bb0a6c182994","email":"[email protected]","createdAt":"2015-03-23T01:22:59.000Z"}
This endpoint starts the OAuth flow. A client redirects the user agent to this url. This endpoint will then redirect to the appropriate content-server page.
client_id
: The id returned from client registration.state
: A value that will be returned to the client as-is upon redirection, so that clients can verify the redirect is authentic.redirect_uri
: Optional. If supplied, a string URL of where to redirect afterwards. Must match URL from registration.scope
: Optional. A space-separated list of scopes that the user has authorized. This could be pruned by the user at the confirmation dialog. If this includes the scopeopenid
, this will be an OpenID Connect authentication request.access_type
: Optional. If provided, should beonline
oroffline
.offline
will result in a refresh_token being provided, so that the access_token can be refreshed after it expires.action
: Optional. If provided, should beemail
,signup
,signin
, orforce_auth
. Send to improve the user experience.- If unspecified then Firefox Accounts will try choose intelligently between
signin
andsignup
based on the user's browser state. email
triggers the email-first flow, which uses the email address to determine whether to display signup or signin. This is becoming the preferred action and is slowly replacingsignin
andsignup
.signin
triggers the signin flow. (will become deprecated and replaced byemail
)signup
triggers the signup flow. (will become deprecated and replaced byemail
)force_auth
requires the user to sign in using the address specified inemail
.
- If unspecified then Firefox Accounts will try choose intelligently between
email
: Optional ifaction
isemail
,signup
orsignin
. Required ifaction
isforce_auth
.- if
action
isemail
, the email address will be used to determine whether to display the signup or signin form, but the user is free to change it. - If
action
issignup
orsignin
, the email address will be pre-filled into the account form, but the user is free to change it. - If
action
issignin
, the literal stringblank
will force the user to enter an email address and the last signed in email address will be ignored. - If
action
issignin
and no email address is specified, the last signed in email address will be used as the default. - If
action
isforce_auth
, the user is unable to modify the email address and is unable to sign up if the address is not registered.
- if
Example:
curl -v "https://oauth.accounts.firefox.com/v1/authorization?client_id=5901bd09376fadaa&state=1234&scope=profile:email&action=signup"
This endpoint should be used by the fxa-content-server, requesting that we supply a short-lived code (currently 15 minutes) that will be sent back to the client. This code will be traded for a token at the token endpoint.
client_id
: The id returned from client registration.assertion
: A FxA assertion for the signed-in user.state
: A value that will be returned to the client as-is upon redirection, so that clients can verify the redirect is authentic.response_type
: Optional. If supplied, must be eithercode
ortoken
.code
is the default.token
means the implicit grant is desired, and requires that the client have special permission to do so.- Note: new implementations should not use
response_type=token
; instead usegrant_type=fxa-credentials
at the token endpoint.
- Note: new implementations should not use
ttl
: Optional ifresponse_type=token
, forbidden ifresponse_type=code
. Indicates the requested lifespan in seconds for the implicit grant token. The value is subject to an internal maximum limit, so clients must check theexpires_in
result property for the actual TTL.redirect_uri
: Optional. If supplied, a string URL of where to redirect afterwards. Must match URL from registration.scope
: Optional. A string-separated list of scopes that the user has authorized. This could be pruned by the user at the confirmation dialog.access_type
: Optional. A value ofoffline
will generate a refresh token along with the access token.code_challenge_method
: Required if using PKCE. Must beS256
, no other value is accepted.code_challenge
: Required if using PKCE. A minimum length of 43 characters and a maximum length of 128 characters string, encoded asBASE64URL
.keys_jwe
: Optional. A JWE bundle to be returned to the client when it redeems the authorization code.acr_values
: Optional. A string-separated list of acr values that the token should have a claim for. SpecifyingAAL2
will require the token to have an authentication assurance level >= 2 which corresponds to requiring 2FA.
Example:
curl -v \
-X POST \
-H "Content-Type: application/json" \
"https://oauth.accounts.firefox.com/v1/authorization" \
-d '{
"client_id": "5901bd09376fadaa",
"assertion": "<assertion>",
"state": "1234",
"scope": "profile:email"
}'
A valid request will return a 200 response, with JSON containing the redirect
to follow. It will include the following query parameters:
code
: A string that the client will trade with the token endpoint. Codes have a configurable expiration value, default is 15 minutes. Codes are single use only.state
: The same value as was passed as a request parameter.
Example:
{
"redirect": "https://example.domain/path?foo=bar&code=4ab433e31ef3a7cf7c20590f047987922b5c9ceb1faff56f0f8164df053dd94c&state=1234"
}
If requesting an implicit grant (token), the response will match the /v1/token response.
After receiving an authorization grant from the user, clients exercise that grant at this endpoint to obtain tokens that can be used to access attached services for a particular user.
The following types of grant are possible:
authorization_code
: a single-use code as produced by the authorization endpoint, obtained through a redirect-based authorization flow.refresh_token
: a token previously obtained from this endpoint when usingaccess_type=offline
.fxa-credentials
: an FxA identity assertion, obtained by directly authenticating the user's account.
ttl
: (optional) Seconds that the access_token should be valid. If unspecified this will default to the maximum value allowed by the server, which is a configurable option but would typically be measured in minutes or hours.grant_type
: Eitherauthorization_code
,refresh_token
, orfxa-credentials
.- If
authorization_code
:client_id
: The id returned from client registration.client_secret
: The secret returned from client registration. Forbidden for public clients, required otherwise.code
: A string that was received from the authorization endpoint.code_verifier
: The PKCE code verifier. Required for public clients, forbidden otherwise.
- If
refresh_token
:client_id
: The id returned from client registration.client_secret
: The secret returned from client registration. Forbidden for public (PKCE) clients, required otherwise.refresh_token
: A string that received from the token endpoint specifically as a refresh token.scope
: (optional) A subset of scopes provided to this refresh_token originally, to receive an access_token with less permissions.
- If
fxa-credentials
:client_id
: The id returned from client registration.assertion
: FxA identity assertion authenticating the user.scope
: (optional) A string-separated list of scopes to be authorized.access_type
: (optional) Determines whether to generate arefresh_token
(ifoffline
) or not (ifonline
).
- If
Example:
curl -v \
-X POST \
-H "Content-Type: application/json" \
"https://oauth.accounts.firefox.com/v1/token" \
-d '{
"client_id": "5901bd09376fadaa",
"client_secret": "20c6882ef864d75ad1587c38f9d733c80751d2cbc8614e30202dc3d1d25301ff",
"ttl": 3600,
"grant_type": "authorization_code",
"code": "4ab433e31ef3a7cf7c20590f047987922b5c9ceb1faff56f0f8164df053dd94c"
}'
A valid request will return a JSON response with these properties:
access_token
: A string that can be used for authorized requests to service providers.scope
: A string of space-separated permissions that this token has.expires_in
: Seconds until this access token will no longer be valid.token_type
: A string representing the token type. Currently will always be "bearer".auth_at
: An integer giving the time at which the user authenticated to the Firefox Accounts server when generating this token, as a UTC unix timestamp (i.e. seconds since epoch).refresh_token
: (Optional) A refresh token to fetch a new access token when this one expires. Only present if:grant_type=authorization_code
and the original authorization request includedaccess_type=offline
.grant_type=fxa-credentials
and the request includedaccess_type=offline
.
id_token
: (Optional) If the authorization was requested withopenid
scope, then this property will contain the OpenID Connect ID Token.keys_jwe
: (Optional) Returns the JWE bundle of key material for any scopes that have keys, ifgrant_type=authorization_code
.
Example:
{
"access_token": "558f9980ad5a9c279beb52123653967342f702e84d3ab34c7f80427a6a37e2c0",
"scope": "profile:email profile:avatar",
"token_type": "bearer",
"expires_in": 3600,
"refresh_token": "58d59cc97c3ca183b3a87a65eec6f93d5be051415b53afbf8491cc4c45dbb0c6",
"auth_at": 1422336613
}
After a client is done using a token, the responsible thing to do is to destroy the token afterwards. A client can use this route to do so.
token|access_token|refresh_token|refresh_token_id
: The hex string access token. By default,token
is assumed to be the access token.
Example:
curl -v \
-X POST \
-H "Content-Type: application/json" \
"https://oauth.accounts.firefox.com/v1/destroy" \
-d '{
"token": "558f9980ad5a9c279beb52123653967342f702e84d3ab34c7f80427a6a37e2c0"
}'
A valid request will return an empty response, with a 200 status code.
Attached services can post tokens to this endpoint to learn about which user and scopes are permitted for the token.
token
: A token string received from a client
Example:
curl -v \
-X POST \
-H "Content-Type: application/json" \
"https://oauth.accounts.firefox.com/v1/verify" \
-d '{
"token": "558f9980ad5a9c279beb52123653967342f702e84d3ab34c7f80427a6a37e2c0"
}'
A valid request will return JSON with these properties:
user
: The uid of the respective user.client_id
: The client_id of the respective client.scope
: An array of scopes allowed for this token.email
: DEPRECATED The email of the respective user.
Example:
{
"user": "5901bd09376fadaa076afacef5251b6a",
"client_id": "45defeda038a1c92",
"scope": ["profile:email", "profile:avatar"],
"email": "[email protected]"
}
This endpoint returns the JWKs that are used for signing OpenID Connect id tokens.
curl -v "https://oauth.accounts.firefox.com/v1/jwks"
A valid response will return JSON of the keys
.
Example:
{
"keys": [
"alg": "RS256",
"use": "sig",
"kty": "RSA",
"kid": "2015.12.02-1",
"n":"xaQHsKpu1KSK-YEMoLzZS7Xxciy3esGrhrrqW_JBrq3IRmeGLaqlE80zcpIVnStyp9tbet2niYTemt8ug591YWO5Y-S0EgQyFTxnGjzNOvAL6Cd2iGie9QeSehfFLNyRPdQiadYw07fw-h5gweMpVJs8nTgS-Bcorlw9JQM6Il1cUpbP0Lt-F_5qrzlaOiTEAAb4JGOusVh0n-MZfKt7w0mikauMH5KfhflwQDn4YTzRkWJzlldXr1Cs0ZkYzOwS4Hcoku7vd6lqCUO0GgZvkuvCFqdVKzpa4CGboNdfIjcGVF4f1CTQaQ0ao51cwLzq1pgi5aWYhVH7lJcm6O_BQw",
"e":"AQAC"
]
}
This endpoint returns the required scoped key metadata.
curl -X POST \
https://oauth.accounts.firefox.com/v1/key-data \
-H 'cache-control: no-cache' \
-H 'content-type: application/json' \
-d '{
"client_id": "aaa6b9b3a65a1871",
"assertion": "eyJhbGciOiJSUzI1NiJ9.eyJwdWJsaWMta2V5Ijp7Imt0eSI6IlJTQSIsIm4iOiJvWmdsNkpwM0Iwcm5BVXppNThrdS1iT0RvR3ZuUGNnWU1UdXQ1WkpyQkJiazBCdWU4VUlRQ0dnYVdrYU5Xb29INkktMUZ6SXU0VFpZYnNqWGJ1c2JRRlQxOGREUkN6VVRubFlXdVZXUzhoSWhKc3lhZHJwSHJOVkI1VndmSlRKZVgwTjFpczBXcU1qdUdOc2VMLXluYnFjOVhueElncFJaai05QnZqY2ZKYXNOUTNZdHR3VHZVaFJOLVFGNWgxQkY1MnA2QmdOTVBvWmQ5MC1EU0xydlpseXp6MEh0Q2tFZnNsc013czVkR0ExTlZ1dEwtcGVDeU50VTFzOEtFaDlzcGxXeF9lQlFybTlYQU1kYXp5ZWR6VUpJU1UyMjZmQzhEUHh5c0ZreXpCbjlDQnFDQUpTNjQzTGFydUVDaS1rMGhKOWFmM2JXTmJnWmpSNVJ2NXF4THciLCJlIjoiQVFBQiJ9LCJwcmluY2lwYWwiOnsiZW1haWwiOiIwNjIxMzM0YzIwNjRjNmYzNmJlOGFkOWE0N2M1NTliY2FwaS5hY2NvdW50cy5maXJlZm94LmNvbSJ9LCJpYXQiOjE1MDY5Njk2OTU0MzksImV4cCI6MTUwNjk2OTY5NjQzOSwiZnhhLXZlcmlmaWVkRW1haWwiOiIzMjM2NzJiZUBtb3ppbGxhLmNvbSIsImlzcyI6ImFwaS5hY2NvdW50cy5maXJlZm94LmNvbSJ9.hFZd5zFheXOFrXKkJvw6Vpv2l7ctlxuBTvuh5f_jLPAjZoJ9ri-vaJjL_WYBFUvS2xHzfx3-ldxLddyTKwCDAJeB_NkOFL_WJSrMet9C7_Z1hH9HmydeXIT82xJmhrwzW-WOO4ibQvRbocEFiNujynKsg1gS8v0iiYjIX-0cXCrlkxkbVx_8EXJFKDDOGzK9v7Zq6D7gkhP-CHEaNYaTHMn65tLQtBS6snGdaXlxoGHMWmDL6STbnJzWa7sa4QwHf-AgT1rUkQQAUHNa_XLZ0FEzqiCPctMadlihiUZL2V6vxIDBS4mHUF4qj0FvIMJflivDnJVkRNijDuP-h-Lh_A~eyJhbGciOiJSUzI1NiJ9.eyJhdWQiOiJvYXV0aC5meGEiLCJleHAiOjE1MDY5Njk2OTY0MzksImlzcyI6ImFwaS5hY2NvdW50cy5maXJlZm94LmNvbSJ9.M5xyk3RffucgaavjbUm7Eqnt47hzeGbGa2VR3jnVEIlRHfz5S25Qf3ngejwee7XECvIywbaKWeijXFOwS-EkB-7qP1gl4oNJjPmbnCk7S1lgckLWvdMIU-HLGKjrN6Mw76__LzvAbsusSeGmsvTCIVuOJ49Xs3tC1fLyB_re0QNpCcS6AUnJ1KOxIMEM3Om7ysNO5F_AqcD3PwlEti5lbwSk8iP5TWL12C2Nkb_6Hxze_mA1NZNAHOips9bF2J7oy1hqGoMYj1XYZrsyjpPWEuZQATAPlKSjbh1hq-UtDeT7DlwEmIbIUd3JA8qh1MkHKGgavd4fIMap0IPmr9rs4A",
"scope": "https://identity.mozilla.com/apps/sample-scope-can-scope-key"
}'
A valid response will return JSON the scoped key information for every scope that has scoped keys:
Example:
{
"https://identity.mozilla.com/apps/sample-scope-can-scope-key": {
"identifier": "https://identity.mozilla.com/apps/sample-scope-can-scope-key",
"keyRotationSecret": "0000000000000000000000000000000000000000000000000000000000000000",
"keyRotationTimestamp": 1506970363512
}
}
This endpoint returns a list of all clients with active OAuth tokens for the user, including the the scopes granted to each client and the last time each client was active. It must be authenticated with an OAuth token bearing scope "clients:write".
Example:
curl -X GET \
https://oauth.accounts.firefox.com/v1/client-tokens \
-H 'cache-control: no-cache' \
-H "Authorization: Bearer 558f9980ad5a9c279beb52123653967342f702e84d3ab34c7f80427a6a37e2c0"
A valid 200 response will be a JSON array where each item as the following properties:
id
: The hex id of the client.name
: The string name of the client.lastAccessTime
: Integer last-access time for the client.lastAccessTimeFormatted
: Localized string last-access time for the client.scope
: Sorted list of all scopes granted to the client.
Example:
[
{
"id": "5901bd09376fadaa",
"name": "Example",
"lastAccessTime": 1528334748000,
"lastAccessTimeFormatted": "13 days ago",
"scope": ["openid", "profile"]
},
{
"id": "23d10a14f474ca41",
"name": "Example Two",
"lastAccessTime": 1476677854037,
"lastAccessTimeFormatted": "2 years ago",
"scope": ["profile:email", "profile:uid"]
}
]
This endpoint deletes all tokens granted to a given client. It must be authenticated with an OAuth token bearing scope "clients:write".
id
: Theclient_id
of the client whose tokens should be deleted.
Example:
curl -X DELETE
https://oauth.accounts.firefox.com/v1/client-tokens/5901bd09376fadaa
-H "Authorization: Bearer 558f9980ad5a9c279beb52123653967342f702e84d3ab34c7f80427a6a37e2c0"
A valid 200 response will return an empty JSON object.