This document provides protocol-level details of the Firefox Accounts Server API. For a prose description of the client/server protocol and details on how each parameter is derived see the API design document.
All requests will be to URLs for the form:
https://<server-url>/v1/<api-endpoint>
Note that:
- All API access must be over a properly-validated HTTPS connection.
- 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:
- For a list of development servers see Firefox Accounts deployments on MDN.
- The canonical URL for Mozilla's hosted Firefox Accounts server is TODO-DEFINE-ME.
Requests that require authentication use Hawk request signatures. These endpoints are marked π in the description below.
All POST requests must have a content-type of application/json
with a utf8-encoded JSON body, and must specify the content-length header. Keys and other binary data are included in the JSON as base16 encoded strings.
The following request headers may be specified to influence the behaviour of the server:
Accept-Language
: may be used to localize verification emails
All successful requests will produce a response with HTTP status code of "200" and content-type of "application/json". The structure of the response body will depend on the endpoint in question.
Successful responses will also include the following headers, which may be useful for the client:
Timestamp
: the current POSIX timestamp as seen by the server, in integer seconds.
Failures due to invalid behavior from the client will produce a response with HTTP status code in the "4XX" range and content-type of "application/json". Failures due to an unexpected situation on the server will produce a response with HTTP status code in the "5XX" range and content-type of "application/json".
To simplify error handling for the client, the type of error is indicated both by a particular HTTP status code, and by an application-specific error code in the JSON response body. For example:
{
"code": 400, // matches the HTTP status code
"errno": 107, // stable application-level error number
"error": "Bad Request", // string description of the error type
"message": "the value of salt is not allowed to be undefined",
"info": "https://docs.dev.lcip.og/errors/1234" // link to more info on the error
}
Responses for particular types of error may include additional parameters.
The currently-defined error responses are:
- status code 400, errno 101: attempt to create an account that already exists
- status code 400, errno 102: attempt to access an account that does not exist
- status code 400, errno 103: incorrect password
- status code 400, errno 104: attempt to operate on an unverified account
- status code 400, errno 105: invalid verification code
- status code 400, errno 106: request body was not valid json
- status code 400, errno 107: request body contains invalid parameters
- status code 400, errno 108: request body missing required parameters
- status code 401, errno 109: invalid request signature
- status code 401, errno 110: invalid authentication token
- status code 401, errno 111: invalid authentication timestamp
- status code 411, errno 112: content-length header was not provided
- status code 413, errno 113: request body too large
- status code 429, errno 114: client has sent too many requests (see backoff protocol)
- status code 401, errno 115: invalid authentication nonce
- status code 410, errno 116: endpoint is no longer supported
- status code 400, errno 117: incorrect login method for this account
- status code 400, errno 118: incorrect key retrieval method for this account
- status code 400, errno 119: incorrect API version for this account
- status code 400, errno 120: incorrect email case
- status code 400, errno 121: account is locked
- status code 400, errno 122: account is not locked
- status code 400, errno 123: unknown device
- status code 400, errno 124: session already registered by another device
- status code 503, errno 201: service temporarily unavailable to due high load (see backoff protocol)
- any status code, errno 999: unknown error
The follow error responses include additional parameters:
- errno 111: a
serverTime
parameter giving the current server time in seconds. - errno 114: a
retryAfter
parameter indicating how long the client should wait before re-trying. - errno 120: a
email
parameter indicating the case used to create the account - errno 201: a
retryAfter
parameter indicating how long the client should wait before re-trying.
Since this is a HTTP-based protocol, clients should be prepared to gracefully handle standard HTTP error responses that may be produced by proxies, load-balancers, or other intermediary servers. Non-application responses can be identified by their lack of properly-formatted JSON response body. Common examples would include:
- "413 Request Entity Too Large" may be produced by an upstream proxy server.
- "502 Gateway Timeout" may be produced by a load-balancer if it cannot contact the application servers.
-
Account
-
Authentication
-
Session
-
Recovery Email
-
Certificate Signing
-
Password
- POST /v1/password/change/start
- POST /v1/password/change/finish (:lock: passwordChangeToken)
- POST /v1/password/forgot/send_code
- POST /v1/password/forgot/resend_code (:lock: passwordForgotToken)
- POST /v1/password/forgot/verify_code (:lock: passwordForgotToken)
- GET /v1/password/forgot/status (:lock: passwordForgotToken)
-
Device registration
-
Miscellaneous
Creates a user account. The client provides the email address with which this account will be labeled and a stretched password. Stretching is detailed on the onepw wiki page.
This endpoint may send a verification email to the user. Callers may optionally provide the service
parameter to indicate what Identity-Attached Service they are acting on behalf of. This is an opaque alphanumeric token which will be embedded in the verification link as a query parameter.
Creating an account also logs in. The response contains a sessionToken
and optionally a keyFetchToken
if the url has a query parameter of keys=true
.
Parameters
- email - the primary email for this account
- authPW - the PBKDF2/HKDF stretched password as a hex string
- service - (optional) opaque alphanumeric token to be included in verification links
- redirectTo - (optional) a URL that the client should be redirected to after handling the request
- resume - (optional) opaque url-encoded string that will be included in the verification link as a querystring parameter, useful for continuing an OAuth flow for example.
- preVerifyToken - (optional) see below
- device - (optional, experimental, DO NOT USE) object containing fields for device registration
curl -v \
-X POST \
-H "Content-Type: application/json" \
"https://api-accounts.dev.lcip.org/v1/account/create?keys=true" \
-d '{
"email": "[email protected]",
"authPW": "996bc6b1aa63cd69856a2ec81cbf19d5c8a604713362df9ee15c2bf07128efab"
}'
Successful requests will produce a "200 OK" response with the account's unique identifier in the JSON body:
{
"uid": "4c352927cd4f4a4aa03d7d1893d950b8",
"sessionToken": "27cd4f4a4aa03d7d186a2ec81cbf19d5c8a604713362df9ee15c4f4a4aa03d7d",
"keyFetchToken": "7d1893d950b8cd69856a2ec81cbfd7d1893d950b3362df9e56a2ec81cbf19d5c",
"authAt": 1392144866
}
- authAt - authentication time for the session (seconds since epoch)
Failing requests may be due to the following errors:
- status code 400, errno 101: attempt to create an account that already exists
- status code 400, errno 105: invalid verification code
- status code 400, errno 106: request body was not valid json
- status code 400, errno 107: request body contains invalid parameters
- status code 400, errno 108: request body missing required parameters
- status code 411, errno 112: content-length header was not provided
- status code 413, errno 113: request body too large
A preVerifyToken
is a signed JWT that certifies that the given email address has already been verified by the issuer.
JOSE Header
- alg - algorithm used to sign this JWT, currently only "RS256" is supported
- kid - key id of the JWK used to sign this JWT
- jku - the url of a JWK set containing the public key used to sign this JWT (must be https)
- example url:
https://nightly.dev.lcip.org/.well-known/public-keys
- example jwk set response:
- example url:
{
"keys":[
{
"kid":"dev-1",
"use": "sig",
"kty":"RSA",
"n":"W_lCUvksZMVxW2JLNtoyPPshvSHng28H5FggSBGBjmzv3eHkMgRdc8hpOkgcPwXYxHdVM6udtVdXZtbGN8nUyQX8gxD3AJg-GSrH3UOsoArPLCmcxwIEpk4B0wqwP68oK8dQHt0iK3N-XeCnMpv75ULlVn3LEOZT8CsuNraVOthYeClUb8r1PjRwqRB06QGNqnnhcPMmh-6cRzQ9HmTMz6CDcugiH5n2sjrvpeBugEsnXt3KpzVdSc4usXrIEmLRuFjwFbkzoo7FiAtSoXxBqc074qz8ejm-V0-2Wv3p6ePeLODeYkPQho4Lb1TBdoidr9RHY29Out4mhzb4nUrHHQ",
"e":"AQAB"
}]
}
Payload
- exp - expiration timestamp
- aud - the public DNS name of the auth-server. ex: api.accounts.firefox.com
- sub - the preverified email address
- typ - must be
"mozilla/fxa/preVerifyToken/v1"
Example
{
//...
"preVerifyToken": "eyJhbGciOiJSUzI1NiIsImprdSI6Imh0dHA6Ly8xMjcuMC4wLjE6OTAwMC8ud2VsbC1rbm93bi9wdWJsaWMta2V5cyIsImtpZCI6ImRldi0xIn0.eyJpc3MiOiIxMjcuMC4wLjEiLCJleHAiOjE0MDkyNjE0NTc0NjIsImF1ZCI6IjEyNy4wLjAuMTo5MDAwIiwic3ViIjoiMC45Njg5NDI5MzQ4ODAwMzMxQGV4YW1wbGUuY29tIn0.541e3ebad20241f4247d483a4ca5b90ab6820d033ed6ff8c3fc0ac399b16ff045c2eb3f28ba83220b726de36c4f928e56664ba22fe470f6850bc3db690c17a1720e8ed5de927896d706ac7b26df90ca146225cfeaa64fb45f0ef0f0f2b06a76c5b763612c6544ba43c82630a26b5aea1675437719a86c264d81ffa71176596731f6c9223c66d959f02beffd3a715c91653c46fdf8f80f155905a468c3d2eadbb2f42ebde5ed8e4eff1f1b5557686ba60364fe6f4fd6d018c980ac91150086b3d3716d363d1c19953a80cf2f246e842b2a480126c116696eab003e6b0abb6ffe4633cdbda09a81c47ed8c7515c4dd37566d6ab1b2b3b9deebda7f45d40dd0f0f4"
}
Gets the status of an account
curl -v "https://api-accounts.dev.lcip.org/v1/account/status?uid=4c352927cd4f4a4aa03d7d1893d950b8"
Successful requests will produce a "200 OK" response with the account status provided in the JSON body:
{
"exists": true,
"locked": false
}
Failing requests may be due to the following errors:
- status code 400, errno 107: request query contains invalid parameters
- status code 400, errno 108: request query missing required parameters
Obtain a sessionToken
and optionally a keyFetchToken
by adding the query parameter keys=true
.
Parameters
- email - the primary email for this account
- authPW - the PBKDF2/HKDF stretched password as a hex string
- service - (optional) opaque alphanumeric token to be included in verification links
- reason - (optional) alphanumeric string indicating the reason for establishing a new session; may be "login" (the default) or "reconnect"
- device - (optional, experimental, DO NOT USE) object containing fields for device registration
curl -v \
-X POST \
-H "Content-Type: application/json" \
https://api-accounts.dev.lcip.org/v1/account/login?keys=true \
-d '{
"email": "[email protected]",
"authPW": "996bc6b1aa63cd69856a2ec81cbf19d5c8a604713362df9ee15c2bf07128efab"
}'
Successful requests will produce a "200 OK" and a json body. keyFetchToken
will only be present if keys=true
was specified.
{
"uid": "4c352927cd4f4a4aa03d7d1893d950b8",
"sessionToken": "27cd4f4a4aa03d7d186a2ec81cbf19d5c8a604713362df9ee15c4f4a4aa03d7d",
"keyFetchToken": "7d1893d950b8cd69856a2ec81cbfd7d1893d950b3362df9e56a2ec81cbf19d5c",
"verified": true,
"authAt": 1392144866
}
- authAt - authentication time for the session (seconds since epoch)
Failing requests may be due to the following errors:
- status code 400, errno 102: attempt to access an account that does not exist
- status code 400, errno 103: incorrect password
- status code 400, errno 106: request body was not valid json
- status code 400, errno 107: request body contains invalid parameters
- status code 400, errno 108: request body missing required parameters
- status code 411, errno 112: content-length header was not provided
- status code 413, errno 113: request body too large
- status code 400, errno 120: incorrect email case
- status code 400, errno 121: account is locked
π HAWK-authenticated with keyFetchToken
Get the base16 bundle of encrypted kA|wrapKb
. The return value must be decrypted with a key derived from keyFetchToken, and then wrapKb
must be further decrypted with a key derived from the user's password.
Since keyFetchToken is single-use, this can only be done once per session. Note that the keyFetchToken is consumed regardless of whether the request succeeds or fails.
This request will fail unless the account's email address has been verified.
Headers
The request must include a HAWK header that authenticates the request using a keyFetchToken
received from /session/create
.
curl -v \
-X GET \
-H "Host: api-accounts.dev.lcip.org" \
-H "Content-Type: application/json" \
-H 'Authorization: Hawk id="d4c5b1e3f5791ef83896c27519979b93a45e6d0da34c7509c5632ac35b28b48d", ts="1373391043", nonce="ohQjqb", mac="LAnpP3P2PXelC6hUoUaHP72nCqY5Iibaa3eeiGBqIIU="' \
https://api-accounts.dev.lcip.org/v1/account/keys \
Successful requests will produce a "200 OK" response with the key data provided in the JSON body as hex-encoded bytes:
{
"bundle": "d486e79c9f3214b0010fe31bfb50fa6c12e1d093f7770c81c6b1c19c7ee375a6558dd1ab38dbc5eba37bc3cfbd6ac040c0208a48ca4f777688a1017e98cedcc1c36ba9c4595088d28dcde5af04ae2215bce907aa6e74dd68481e3edc6315d47efa6c7b6536e8c0adff9ca426805e9479607b7c105050f1391dffed2a9826b8ad"
}
See decrypting the bundle
for info on how to extract kA|wrapKb
from the bundle.
Failing requests may be due to the following errors:
- status code 400, errno 104: attempt to operate on an unverified account
- status code 401, errno 109: invalid request signature
- status code 401, errno 110: invalid authentication token
- status code 401, errno 111: invalid authentication timestamp
- status code 401, errno 115: invalid authentication nonce
π OAuth Bearer token, or HAWK-authenticated with sessionToken
Get the email and locale of a user.
If an OAuth Bearer token is used, the values returned depend on the scopes that the token is authorized for.
email
requiresprofile:email
scopelocale
requireprofile:locale
scope
The profile
scope includes both of the above sub-scopes.
Headers
The request must include an OAuth Bearer token, or a HAWK header that authenticates the request using a sessionToken
received from /account/login
.
curl -v \
-X GET \
-H "Host: api-accounts.dev.lcip.org" \
-H "Content-Type: application/json" \
-H 'Authorization: Bearer d4c5b1e3f5791ef83896c27519979b93a45e6d0da34c7509c5632ac35b28b48d' \
https://api-accounts.dev.lcip.org/v1/account/keys \
Successful requests will produce a "200 OK" response with data returned as JSON:
{
"email": "[email protected]",
"locale": "hi-IN"
}
π HAWK-authenticated with accountResetToken
This sets the account password and resets wrapKb to a new random value.
The accountResetToken is single-use, and is consumed regardless of whether the request succeeds or fails.
Parameters
- authPW - the PBKDF2/HKDF stretched password as a hex string
Headers
The request must include a HAWK header that authenticates the request (including payload) using a key derived from the accountResetToken
, which is returned by /v1/password/forgot/verify_code
.
curl -v \
-X POST \
-H "Host: api-accounts.dev.lcip.org" \
-H "Content-Type: application/json" \
-H 'Authorization: Hawk id="d4c5b1e3f5791ef83896c27519979b93a45e6d0da34c7509c5632ac35b28b48d", ts="1373391043", nonce="ohQjqb", hash="vBODPWhDhiRWM4tmI9qp+np+3aoqEFzdGuGk0h7bh9w=", mac="LAnpP3P2PXelC6hUoUaHP72nCqY5Iibaa3eeiGBqIIU="' \
https://api-accounts.dev.lcip.org/v1/account/reset \
-d '{
"authPW": "f9fae9253549b2428a403d6fa51e6fb43d2f8a302e132cf902ffade52c02e6a4"
}
}'
Successful requests will produce a "200 OK" response with empty JSON body:
{}
Failing requests may be due to the following errors:
- status code 400, errno 106: request body was not valid json
- status code 400, errno 107: request body contains invalid parameters
- status code 400, errno 108: request body missing required parameters
- status code 401, errno 109: invalid request signature
- status code 401, errno 110: invalid authentication token
- status code 401, errno 111: invalid authentication timestamp
- status code 411, errno 112: content-length header was not provided
- status code 413, errno 113: request body too large
- status code 401, errno 115: invalid authentication nonce
This deletes the account completely. All stored data is erased. The client should seek user confirmation first. The client should erase data stored on any attached services before deleting the user's account data.
Parameters
- email - the account email address
- authPW - the PBKDF2/HKDF stretched password as a hex string
curl -v \
-X POST \
-H "Host: api-accounts.dev.lcip.org" \
-H "Content-Type: application/json" \
https://api-accounts.dev.lcip.org/v1/account/destroy \
-d '{
"email": "[email protected]",
"authPW": "f9fae9253549b2428a403d6fa51e6fb43d2f8a302e132cf902ffade52c02e6a4"
}'
Successful requests will produce a "200 OK" response with empty JSON body:
{}
Failing requests may be due to the following errors:
- status code 400, errno 102: attempt to access an account that does not exist
- status code 400, errno 103: incorrect password
- status code 400, errno 106: request body was not valid json
- status code 401, errno 109: invalid request signature
- status code 401, errno 110: invalid authentication token
- status code 401, errno 111: invalid authentication timestamp
- status code 411, errno 112: content-length header was not provided
- status code 413, errno 113: request body too large
- status code 401, errno 115: invalid authentication nonce
- status code 400, errno 120: incorrect email case
- status code 400, errno 121: account is locked
HAWK-authenticated.
This locks an account and prevents the user from performing any action that requires a password until their email address is re-verified. This endpoint is for testing only and is disabled for production.
Parameters
- email - the email address for the account
- authPW - the PBKDF2/HKDF stretched password as a hex string
curl -v \
-X POST \
-H "Content-Type: application/json" \
https://api-accounts.dev.lcip.org/v1/account/lock \
-d '{
"email": "[email protected]",
"authPW": "996bc6b1aa63cd69856a2ec81cbf19d5c8a604713362df9ee15c2bf07128efab"
}'
Successful requests will produce a "200 OK" and a json body.
{}
Failing requests may be due to the following errors:
- status code 400, errno 102: attempt to access an account that does not exist
- status code 400, errno 103: incorrect password
- status code 400, errno 106: request body was not valid json
- status code 400, errno 107: request body contains invalid parameters
- status code 400, errno 108: request body missing required parameters
- status code 411, errno 112: content-length header was not provided
- status code 413, errno 113: request body too large
Not HAWK-authenticated.
Re-sends an account unlock code to the account's recovery email address. The code is first sent when the account is locked due to suspicious activity, but if the user thinks the message was lost or accidentally deleted, they can request a new message to be sent with this endpoint. The new message will contain the same code as the original message. When this code is provided to /v1/account/unlock/verify_code
(below), the account will be unlocked.
Parameters
- email - the recovery email for this account
- service - (optional) indicates the relying service that the user was interacting with that triggered the account lockout message
- redirectTo - (optional) a URL that the client should be redirected to after handling the request
- resume - (optional) opaque url-encoded string that will be included in the verification link as a querystring parameter, useful for continuing an OAuth flow for example.
curl -v \
-X POST \
-H "Content-Type: application/json" \
https://api-accounts.dev.lcip.org/v1/account/unlock/resend_code \
-d '{
"email": "[email protected]",
"service": "sync",
"redirectTo": "https://sync.firefox.com/after_unlock"
}'
Successful requests will produce a "200 OK" response with an empty JSON body:
{}
Failing requests may be due to the following errors:
- status code 400, errno 102: attempt to access an account that does not exist
- status code 400, errno 106: request body was not valid json
- status code 400, errno 107: request body contains invalid parameters
- status code 400, errno 108: request body missing required parameters
- status code 411, errno 112: content-length header was not provided
- status code 413, errno 113: request body too large
- status code 400, errno 122: account is not locked
Not HAWK-authenticated.
Used to submit an account unlock code that was previously sent to a user's recovery email. If correct, the account will be unlocked.
The unlock code will be a random token, delivered in the fragment portion of a URL sent to the user's email address. The URL will lead to a page that extracts the code from the URL fragment, and performs a POST to /account/unlock/verify_code
. The link can be clicked from any browser, not just the one being attached to the account.
Parameters
- uid - account identifier
- code - the verification code
curl -v \
-X POST \
-H "Host: api-accounts.dev.lcip.org" \
-H "Content-Type: application/json" \
https://api-accounts.dev.lcip.org/v1/account/unlock/verify_code \
-d '{
"uid": "4c352927cd4f4a4aa03d7d1893d950b8",
"code": "e3c5b0e3f5391e134596c27519979b93"
}'
Successful requests will produce a "200 OK" response with an empty JSON body:
{}
Failing requests may be due to the following errors:
- status code 400, errno 105: invalid verification code
- status code 400, errno 106: request body was not valid json
- status code 400, errno 107: request body contains invalid parameters
- status code 400, errno 108: request body missing required parameters
- status code 411, errno 112: content-length header was not provided
- status code 413, errno 113: request body too large
π HAWK-authenticated with the sessionToken.
The request will return a success response as long as the token is valid.
Headers
The request must include a Hawk header that authenticates the request using a sessionToken
received from /v1/account/create
or /v1/account/login
.
curl -v \
-X GET \
-H "Host: api-accounts.dev.lcip.org" \
-H "Content-Type: application/json" \
-H 'Authorization: Hawk id="d4c5b1e3f5791ef83896c27519979b93a45e6d0da34c7509c5632ac35b28b48d", ts="1373391043", nonce="ohQjqb", hash="vBODPWhDhiRWM4tmI9qp+np+3aoqEFzdGuGk0h7bh9w=", mac="LAnpP3P2PXelC6hUoUaHP72nCqY5Iibaa3eeiGBqIIU="' \
https://api-accounts.dev.lcip.org/v1/session/status \
Successful requests will produce a "200 OK" response with the account uid in the JSON body object:
{
"uid": "80dc2f2e373b4b3bb992468e6d578cd2"
}
Failing requests may be due to the following errors:
- status code 401, errno 109: invalid request signature
- status code 401, errno 110: invalid authentication token
- status code 401, errno 111: invalid authentication timestamp
- status code 401, errno 115: invalid authentication nonce
π HAWK-authenticated with the sessionToken.
Destroys this session, by invalidating the sessionToken. This is used when a device "signs-out", detaching itself from the account. After calling this, the device must re-perform the /v1/account/login
sequence to obtain a new sessionToken.
Headers
The request must include a Hawk header that authenticates the request using a sessionToken
received from /v1/account/login
.
curl -v \
-X POST \
-H "Host: api-accounts.dev.lcip.org" \
-H "Content-Type: application/json" \
-H 'Authorization: Hawk id="d4c5b1e3f5791ef83896c27519979b93a45e6d0da34c7509c5632ac35b28b48d", ts="1373391043", nonce="ohQjqb", mac="LAnpP3P2PXelC6hUoUaHP72nCqY5Iibaa3eeiGBqIIU="' \
https://api-accounts.dev.lcip.org/v1/session/destroy \
Successful requests will produce a "200 OK" response with an empty JSON body:
{}
Failing requests may be due to the following errors:
- status code 400, errno 106: request body was not valid json
- status code 401, errno 109: invalid request signature
- status code 401, errno 110: invalid authentication token
- status code 401, errno 111: invalid authentication timestamp
- status code 411, errno 112: content-length header was not provided
- status code 413, errno 113: request body too large
- status code 401, errno 115: invalid authentication nonce
π HAWK-authenticated with the sessionToken.
Returns the "verified" status for the account's recovery email address.
Currently, each account is associated with exactly one email address. This address must be "verified" before the account can be used (specifically, /v1/certificate/sign
and /v1/account/keys
will return errors until the address is verified). In the future, this may be expanded to include multiple addresses, and/or alternate types of recovery methods (e.g., SMS). A new API will be provided for this extra functionality.
This call is used to determine the current state (verified or unverified) of the recovery email address. During account creation, until the address is verified, the agent can poll this method to discover when it should proceed with /v1/certificate/sign
and /v1/account/keys
.
Headers
The request must include a Hawk header that authenticates the request using a sessionToken
received from /v1/account/login
.
curl -v \
-X GET \
-H "Host: api-accounts.dev.lcip.org" \
-H "Content-Type: application/json" \
-H 'Authorization: Hawk id="d4c5b1e3f5791ef83896c27519979b93a45e6d0da34c7509c5632ac35b28b48d", ts="1373391043", nonce="ohQjqb", hash="vBODPWhDhiRWM4tmI9qp+np+3aoqEFzdGuGk0h7bh9w=", mac="LAnpP3P2PXelC6hUoUaHP72nCqY5Iibaa3eeiGBqIIU="' \
https://api-accounts.dev.lcip.org/v1/recovery_email/status \
Successful requests will produce a "200 OK" response with the account email and verification status in the JSON body object:
{ "email": "[email protected]", "verified": true }
Failing requests may be due to the following errors:
- status code 401, errno 109: invalid request signature
- status code 401, errno 110: invalid authentication token
- status code 401, errno 111: invalid authentication timestamp
- status code 401, errno 115: invalid authentication nonce
π HAWK-authenticated with the sessionToken.
Re-sends a verification code to the account's recovery email address. The code is first sent when the account is created, but if the user thinks the message was lost or accidentally deleted, they can request a new message to be sent with this endpoint. The new message will contain the same code as the original message. When this code is provided to /v1/recovery_email/verify_code
(below), the email will be marked as "verified".
This endpoint may send a verification email to the user. Callers may optionally provide the service
parameter to indicate what Identity-Attached Service they are acting on behalf of. This is an opaque alphanumeric token which will be embedded in the verification link as a query parameter.
Parameters
- service - (optional) opaque alphanumeric token to be included in verification links
- redirectTo - (optional) a URL that the client should be redirected to after handling the request
- resume - (optional) opaque url-encoded string that will be included in the verification link as a querystring parameter, useful for continuing an OAuth flow for example.
Headers
The request must include a Hawk header that authenticates the request (including payload) using a sessionToken
received from /v1/session/create
.
curl -v \
-X POST \
-H "Host: api-accounts.dev.lcip.org" \
-H "Content-Type: application/json" \
-H 'Authorization: Hawk id="d4c5b1e3f5791ef83896c27519979b93a45e6d0da34c7509c5632ac35b28b48d", ts="1373391043", nonce="ohQjqb", hash="vBODPWhDhiRWM4tmI9qp+np+3aoqEFzdGuGk0h7bh9w=", mac="LAnpP3P2PXelC6hUoUaHP72nCqY5Iibaa3eeiGBqIIU="' \
https://api-accounts.dev.lcip.org/v1/recovery_email/resend_code
Successful requests will produce a "200 OK" response with an empty JSON body:
{}
Failing requests may be due to the following errors:
- status code 400, errno 106: request body was not valid json
- status code 401, errno 109: invalid request signature
- status code 401, errno 110: invalid authentication token
- status code 401, errno 111: invalid authentication timestamp
- status code 411, errno 112: content-length header was not provided
- status code 413, errno 113: request body too large
- status code 401, errno 115: invalid authentication nonce
Not HAWK-authenticated.
Used to submit a verification code that was previously sent to a user's recovery email. If correct, the account's recovery email address will be marked as "verified".
The verification code will be a random token, delivered in the fragment portion of a URL sent to the user's email address. The URL will lead to a page that extracts the code from the URL fragment, and performs a POST to /recovery_email/verify_code
. The link can be clicked from any browser, not just the one being attached to the Firefox account.
Parameters
- uid - account identifier
- code - the verification code
curl -v \
-X POST \
-H "Host: api-accounts.dev.lcip.org" \
-H "Content-Type: application/json" \
https://api-accounts.dev.lcip.org/v1/recovery_email/verify_code \
-d '{
"uid": "4c352927cd4f4a4aa03d7d1893d950b8",
"code": "e3c5b0e3f5391e134596c27519979b93"
}'
Successful requests will produce a "200 OK" response with an empty JSON body:
{}
Failing requests may be due to the following errors:
- status code 400, errno 102: attempt to access an account that does not exist
- status code 400, errno 105: invalid verification code
- status code 400, errno 106: request body was not valid json
- status code 400, errno 107: request body contains invalid parameters
- status code 400, errno 108: request body missing required parameters
- status code 411, errno 112: content-length header was not provided
- status code 413, errno 113: request body too large
π HAWK-authenticated with the sessionToken.
Sign a BrowserID public key. The server is given a public key, and returns a signed certificate using the same JWT-like mechanism as a BrowserID primary IdP would (see the browserid-certifier project for details). The signed certificate includes a principal.email
property to indicate the Firefox Account identifier (a uuid at the account server's primary domain) and is stamped with an expiry time based on the "duration" parameter.
This request will fail unless the account's email address has been verified.
Parameters
- publicKey - the key to sign (run
bin/generate-keypair
from browserid-crypto)- algorithm - "RS" or "DS"
- n - RS only
- e - RS only
- y - DS only
- p - DS only
- q - DS only
- g - DS only
- duration - time interval from now when the certificate will expire, in milliseconds, up to a maximum of 24 hours.
Headers
The request must include a Hawk header that authenticates the request (including payload) using a sessionToken
received from /v1/account/login
.
curl -v \
-X POST \
-H "Host: api-accounts.dev.lcip.org" \
-H "Content-Type: application/json" \
-H 'Authorization: Hawk id="d4c5b1e3f5791ef83896c27519979b93a45e6d0da34c7509c5632ac35b28b48d", ts="1373391043", nonce="ohQjqb", hash="vBODPWhDhiRWM4tmI9qp+np+3aoqEFzdGuGk0h7bh9w=", mac="LAnpP3P2PXelC6hUoUaHP72nCqY5Iibaa3eeiGBqIIU="' \
https://api-accounts.dev.lcip.org/v1/certificate/sign \
-d '{
"publicKey": {
"algorithm":"RS",
"n":"4759385967235610503571494339196749614544606692567785790953934768202714280652973091341316862993582789079872007974809511698859885077002492642203267408776123",
"e":"65537"
},
"duration": 86400000
}'
Successful requests will produce a "200 OK" response with the signed identity certificate in the JSON body object:
{
"cert": "eyJhbGciOiJEUzI1NiJ9.eyJwdWJsaWMta2V5Ijp7ImFsZ29yaXRobSI6IlJTIiwibiI6IjU3NjE1NTUwOTM3NjU1NDk2MDk4MjAyMjM2MDYyOTA3Mzg5ODMyMzI0MjUyMDY2Mzc4OTA0ODUyNDgyMjUzODg1MTA3MzQzMTY5MzI2OTEyNDkxNjY5NjQxNTQ3NzQ1OTM3NzAxNzYzMTk1NzQ3NDI1NTEyNjU5NjM2MDgwMzYzNjE3MTc1MzMzNjY5MzEyNTA2OTk1MzMyNDMiLCJlIjoiNjU1MzcifSwicHJpbmNpcGFsIjp7ImVtYWlsIjoiZm9vQGV4YW1wbGUuY29tIn0sImlhdCI6MTM3MzM5MjE4OTA5MywiZXhwIjoxMzczMzkyMjM5MDkzLCJpc3MiOiIxMjcuMC4wLjE6OTAwMCJ9.l5I6WSjsDIwCKIz_9d3juwHGlzVcvI90T2lv2maDlr8bvtMglUKFFWlN_JEzNyPBcMDrvNmu5hnhyN7vtwLu3Q"
}
The signed certificate includes these additional claims:
- fxa-generation - a number that increases each time the user's password is changed
- fxa-lastAuthAt - authentication time for this session (seconds since epoch)
- fxa-verifiedEmail - the user's verified recovery email address
Failing requests may be due to the following errors:
- status code 400, errno 104: attempt to operate on an unverified account
- status code 400, errno 106: request body was not valid json
- status code 400, errno 107: request body contains invalid parameters
- status code 400, errno 108: request body missing required parameters
- status code 401, errno 109: invalid request signature
- status code 401, errno 110: invalid authentication token
- status code 401, errno 111: invalid authentication timestamp
- status code 411, errno 112: content-length header was not provided
- status code 413, errno 113: request body too large
- status code 401, errno 115: invalid authentication nonce
Begin the "change password" process. It returns a single-use passwordChangeToken
, which will be delivered to /v1/password/change/finish
. It also returns a single-use keyFetchToken
.
Parameters
- email - the account email address
- oldAuthPW - the PBKDF2/HKDF stretched password as a hex string
curl -v \
-X POST \
-H "Content-Type: application/json" \
https://api-accounts.dev.lcip.org/v1/password/change/start \
-d '{
"email": "[email protected]",
"oldAuthPW": "d486e79c9f3214b0010fe31bfb50fa6c12e1d093f7770c81c6b1c19c7ee375a6"
}'
Successful requests will produce a "200 OK" response with the encrypted sessionToken+keyFetchToken bundle in the JSON body object:
{
"keyFetchToken": "fa6c7b6536e8c0adff9ca426805e9479607b7c105050f1391dffed2a9826b8ad",
"passwordChangeToken": "0208a48ca4f777688a1017e98cedcc1c36ba9c4595088d28dcde5af04ae2215b",
"verified": true
}
Failing requests may be due to the following errors:
- status code 400, errno 102: attempt to access an account that does not exist
- status code 400, errno 103: incorrect password
- status code 400, errno 106: request body was not valid json
- status code 411, errno 112: content-length header was not provided
- status code 413, errno 113: request body too large
- status code 400, errno 120: incorrect email case
- status code 400, errno 121: account is locked
π HAWK-authenticated with the passwordChangeToken.
Change the password and update wrapKb
.
Parameters
- authPW - the new PBKDF2/HKDF stretched password as a hex string
- wrapKb - the new wrapKb value as a hex string
curl -v \
-X POST \
-H "Content-Type: application/json" \
-H 'Authorization: Hawk id="d4c5b1e3f5791ef83896c27519979b93a45e6d0da34c7509c5632ac35b28b48d", ts="1373391043", nonce="ohQjqb", mac="LAnpP3P2PXelC6hUoUaHP72nCqY5Iibaa3eeiGBqIIU="' \
https://api-accounts.dev.lcip.org/v1/password/change/finish \
-d '{
"authPW": "761443da0ab27b1fa18c98912af6291714e9600aa3499109c5632ac35b28a309",
"wrapKb": "20e3f5391e134596c27519979b93a45e6d0da34c75ac55c0520f2edfb0267614"
}'
Successful requests will produce a "200 OK" response with an empty JSON body:
{}
Failing requests may be due to the following errors:
- status code 400, errno 106: request body was not valid json
- status code 400, errno 107: request body contains invalid parameters
- status code 400, errno 108: request body missing required parameters
- status code 401, errno 109: invalid request signature
- status code 401, errno 110: invalid authentication token
- status code 401, errno 111: invalid authentication timestamp
- status code 411, errno 112: content-length header was not provided
- status code 413, errno 113: request body too large
- status code 401, errno 115: invalid authentication nonce
Not HAWK-authenticated.
This requests a "reset password" code to be sent to the user's recovery email. The user should type this code into the agent, which will then submit it to /v1/password/forgot/verify_code
(described below). verify_code
will then return a accountResetToken
, which can be used to reset the account password.
This code will be either 8 or 16 digits long, and the send_code
response indicates the code length (so the UI can display a suitable input form). The email will either contain the code itself, or will contain a link to a web page which will display the code.
The send_code
response includes a passwordForgotToken
, which must be submitted with the code to /v1/password/forgot/verify_code
later.
The response also specifies the ttl of this token, and a limit on the number of times verify_code
can be called with this token. By limiting the number of submission attempts, we also limit an attacker's ability to guess the code. After the token expires, or the maximum number of submissions have happened, the agent must use send_code
again to generate a new code and token.
Each account can have at most one passwordForgotToken
valid at a time. Calling send_code
causes any existing tokens to be canceled and a new one created. Each token is associated with a specific code, so send_code
also invalidates any existing codes.
Parameters
- email - the recovery email for this account
- service - (optional) indicates the relying service that the user was interacting with that triggered the password reset
- redirectTo - (optional) a URL that the client should be redirected to after handling the request
- resume - (optional) opaque url-encoded string that will be included in the verification link as a querystring parameter, useful for continuing an OAuth flow for example.
curl -v \
-X POST \
-H "Content-Type: application/json" \
https://api-accounts.dev.lcip.org/v1/password/forgot/send_code \
-d '{
"email": "[email protected]",
"service": "sync",
"redirectTo": "https://sync.firefox.com/after_reset"
}'
Successful requests will produce a "200 OK" response with details of the reset code in the JSON body object:
{
"passwordForgotToken": "10ce20e3f5391e134596c27519979b93a45e6d0da34c75ac55c0520f2edfb026761443da0ab27b1fa18c98912af6291714e9600aa3499109c5632ac35b28a309",
"ttl": 900,
"codeLength": 8,
"tries": 3
}
Failing requests may be due to the following errors:
- status code 400, errno 102: attempt to access an account that does not exist
- status code 400, errno 106: request body was not valid json
- status code 400, errno 107: request body contains invalid parameters
- status code 400, errno 108: request body missing required parameters
- status code 411, errno 112: content-length header was not provided
- status code 413, errno 113: request body too large
π HAWK-authenticated with the passwordForgotToken.
While the agent is waiting for the user to paste in the forgot-password code, if the user believes the email has been lost or accidentally deleted, the /v1/password/forgot/resend_code
API can be used to send a new copy of the same code.
This API requires the passwordForgotToken
returned by the original send_code
call (only the original browser which started the process may request a replacement message). It will return the same response as send_code
did, except with a shorter ttl
indicating the remaining validity period. If verify_code
has been called some number of times with the same token, then tries
will be smaller too.
Parameters
- email - the recovery email for this account
- service - (optional) indicates the relying service that the user was interacting with that triggered the password reset
- redirectTo - (optional) a URL that the client should be redirected to after handling the request
- resume - (optional) opaque url-encoded string that will be included in the verification link as a querystring parameter, useful for continuing an OAuth flow for example.
curl -v \
-X POST \
-H "Content-Type: application/json" \
-H 'Authorization: Hawk id="d4c5b1e3f5791ef83896c27519979b93a45e6d0da34c7509c5632ac35b28b48d", ts="1373391043", nonce="ohQjqb", mac="LAnpP3P2PXelC6hUoUaHP72nCqY5Iibaa3eeiGBqIIU="' \
https://api-accounts.dev.lcip.org/v1/password/forgot/resend_code \
-d '{
"email": "[email protected]"
}'
Successful requests will produce a "200 OK" response with details of the reset code in the JSON body object:
{
"passwordForgotToken": "10ce20e3f5391e134596c27519979b93a45e6d0da34c75ac55c0520f2edfb026761443da0ab27b1fa18c98912af6291714e9600aa3499109c5632ac35b28a309",
"ttl": 550,
"codeLength": 8,
"tries": 2
}
Failing requests may be due to the following errors:
- status code 400, errno 102: attempt to access an account that does not exist
- status code 400, errno 106: request body was not valid json
- status code 400, errno 107: request body contains invalid parameters
- status code 400, errno 108: request body missing required parameters
- status code 401, errno 109: invalid request signature
- status code 401, errno 110: invalid authentication token
- status code 401, errno 111: invalid authentication timestamp
- status code 411, errno 112: content-length header was not provided
- status code 413, errno 113: request body too large
- status code 401, errno 115: invalid authentication nonce
π HAWK-authenticated with the passwordForgotToken.
Once the code created by /v1/password/forgot/send_code
is emailed to the user, and they paste it into their browser, the browser agent should deliver it to this verify_code
endpoint (along with the passwordForgotToken
). This will cause the server to allocate and return an accountResetToken
, which can be used to reset the account password and wrap(kB) with the /v1/account/reset
API (described above).
Parameters
- code - the code sent to the user's recovery method
curl -v \
-X POST \
-H "Content-Type: application/json" \
-H 'Authorization: Hawk id="d4c5b1e3f5791ef83896c27519979b93a45e6d0da34c7509c5632ac35b28b48d", ts="1373391043", nonce="ohQjqb", mac="LAnpP3P2PXelC6hUoUaHP72nCqY5Iibaa3eeiGBqIIU="' \
https://api-accounts.dev.lcip.org/v1/password/forgot/verify_code \
-d '{
"code": "12345678"
}'
Successful requests will produce a "200 OK" response with accountResetToken in the JSON body object, as unencrypted hex-encoded bytes:
{
"accountResetToken": "99ce20e3f5391e134596c2ac55c0520f2edfb026761443da0ab27b1fa18c98912af6291714e9600aa349917519979b93a45e6d0da34c7509c5632ac35b2865d3"
}
Failing requests may be due to the following errors:
- status code 400, errno 105: invalid verification code
- status code 400, errno 106: request body was not valid json
- status code 400, errno 107: request body contains invalid parameters
- status code 400, errno 108: request body missing required parameters
- status code 401, errno 109: invalid request signature
- status code 401, errno 110: invalid authentication token
- status code 401, errno 111: invalid authentication timestamp
- status code 411, errno 112: content-length header was not provided
- status code 413, errno 113: request body too large
- status code 401, errno 115: invalid authentication nonce
π HAWK-authenticated with the passwordForgotToken.
Returns the status for the passwordForgotToken. If the request returns a success response, the token has not yet been consumed. When the token is consumed by a successful reset or expires you can expect to get a 401 HTTP status code with an errno of 110.
Headers
The request must include a Hawk header that authenticates the request using a passwordForgotToken
received from /v1/password/forgot/send_code
.
curl -v \
-X GET \
-H "Host: api-accounts.dev.lcip.org" \
-H "Content-Type: application/json" \
-H 'Authorization: Hawk id="d4c5b1e3f5791ef83896c27519979b93a45e6d0da34c7509c5632ac35b28b48d", ts="1373391043", nonce="ohQjqb", hash="vBODPWhDhiRWM4tmI9qp+np+3aoqEFzdGuGk0h7bh9w=", mac="LAnpP3P2PXelC6hUoUaHP72nCqY5Iibaa3eeiGBqIIU="' \
https://api-accounts.dev.lcip.org/v1/password/forgot/status \
Successful requests will produce a "200 OK" response with the tries and ttl in the JSON body object:
{ "tries": 3, "ttl": 420 }
Failing requests may be due to the following errors:
- status code 401, errno 109: invalid request signature
- status code 401, errno 110: invalid authentication token
- status code 401, errno 111: invalid authentication timestamp
- status code 401, errno 115: invalid authentication nonce
π HAWK-authenticated with the sessionToken.
Either registers a new device for this user/session
(if a device id
is not specified)
or updates existing device details for this user/session
(if a device id
is specified).
If no device id
is specified,
both name
and type
must be provided.
If a device id
is specified,
at least one of name
, type
, pushCallback
and pushPublicKey
must be present.
Headers
The request must include a Hawk header that authenticates the request
using a sessionToken
received from /v1/account/create
or /v1/account/login
.
curl -v \
-X POST \
-H "Host: api-accounts.dev.lcip.org" \
-H "Content-Type: application/json" \
-H 'Authorization: Hawk id="d4c5b1e3f5791ef83896c27519979b93a45e6d0da34c7509c5632ac35b28b48d", ts="1373391043", nonce="ohQjqb", hash="vBODPWhDhiRWM4tmI9qp+np+3aoqEFzdGuGk0h7bh9w=", mac="LAnpP3P2PXelC6hUoUaHP72nCqY5Iibaa3eeiGBqIIU="' \
https://api-accounts.dev.lcip.org/v1/account/device \
-d '{
"name": "My Phone",
"type": "mobile",
"pushCallback": "https://updates.push.services.mozilla.com/update/abcdef01234567890abcdefabcdef01234567890abcdef",
"pushPublicKey": "468601214f60f4828b6cd5d51d9d99d212e7c73657978955f0f5a5b7e2fa1370"
}'
curl -v \
-X POST \
-H "Host: api-accounts.dev.lcip.org" \
-H "Content-Type: application/json" \
-H 'Authorization: Hawk id="d4c5b1e3f5791ef83896c27519979b93a45e6d0da34c7509c5632ac35b28b48d", ts="1373391043", nonce="ohQjqb", hash="vBODPWhDhiRWM4tmI9qp+np+3aoqEFzdGuGk0h7bh9w=", mac="LAnpP3P2PXelC6hUoUaHP72nCqY5Iibaa3eeiGBqIIU="' \
https://api-accounts.dev.lcip.org/v1/account/device \
-d '{
"id": "0f7aa00356e5416e82b3bef7bc409eef",
"name": "My Old Phone"
}'
Successful requests will return a 200 OK
response
with an object that contains the device id in the JSON body:
{
"id": "0f7aa00356e5416e82b3bef7bc409eef",
"createdAt": 1447755864288,
"name": "My Phone",
"type": "mobile",
"pushCallback": "https://updates.push.services.mozilla.com/update/abcdef01234567890abcdefabcdef01234567890abcdef",
"pushPublicKey": "468601214f60f4828b6cd5d51d9d99d212e7c73657978955f0f5a5b7e2fa1370"
}
Failing requests may return the following errors:
- status code 400, errno 123: unknown device
- status code 400, errno 124: session already registered by another device
π HAWK-authenticated with the sessionToken.
Returns the list of all registered devices for the authenticated user.
Headers
The request must include a Hawk header that authenticates the request
using a sessionToken
received from /v1/account/create
or /v1/account/login
.
curl -v \
-X GET \
-H "Host: api-accounts.dev.lcip.org" \
-H 'Authorization: Hawk id="d4c5b1e3f5791ef83896c27519979b93a45e6d0da34c7509c5632ac35b28b48d", ts="1373391043", nonce="ohQjqb", hash="vBODPWhDhiRWM4tmI9qp+np+3aoqEFzdGuGk0h7bh9w=", mac="LAnpP3P2PXelC6hUoUaHP72nCqY5Iibaa3eeiGBqIIU="' \
https://api-accounts.dev.lcip.org/v1/account/devices
Successful requests will return a 200 OK
response
with an array of device details in the JSON body:
[
{
"id": "0f7aa00356e5416e82b3bef7bc409eef",
"isCurrentDevice": true,
"lastAccessTime": 1449235471335,
"name": "My Phone",
"type": "mobile",
"pushCallback": "https://updates.push.services.mozilla.com/update/abcdef01234567890abcdefabcdef01234567890abcdef",
"pushPublicKey": "468601214f60f4828b6cd5d51d9d99d212e7c73657978955f0f5a5b7e2fa1370"
},
{
"id": "0f7aa00356e5416e82b3bef7bc409eef",
"isCurrentDevice": false,
"lastAccessTime": 1417699471335,
"name": "My Desktop",
"type": null,
"pushCallback": "https://updates.push.services.mozilla.com/update/d4c5b1e3f5791ef83896c27519979b93a45e6d0da34c75",
"pushPublicKey": "468601214f60f4828b6cd5d51d9d99d212e7c73657978955f0f5a5b7e2fa1370"
}
]
Failing requests may return the following error:
- status code 400, errno 102: unknown account
π HAWK-authenticated with the sessionToken.
Destroys an existing device record and its associated sessionToken for the authenticated user. The identified device must sign in again to use the API after this request has succeeded.
Headers
The request must include a Hawk header that authenticates the request
using a sessionToken
received from /v1/account/create
or /v1/account/login
.
curl -v \
-X POST \
-H "Host: api-accounts.dev.lcip.org" \
-H "Content-Type: application/json" \
-H 'Authorization: Hawk id="d4c5b1e3f5791ef83896c27519979b93a45e6d0da34c7509c5632ac35b28b48d", ts="1373391043", nonce="ohQjqb", hash="vBODPWhDhiRWM4tmI9qp+np+3aoqEFzdGuGk0h7bh9w=", mac="LAnpP3P2PXelC6hUoUaHP72nCqY5Iibaa3eeiGBqIIU="' \
https://api-accounts.dev.lcip.org/v1/account/device/destroy \
-d '{
"id": "0f7aa00356e5416e82b3bef7bc409eef"
}'
Successful requests will return a 200 OK
response
with an empty object in the JSON body:
{}
Failing requests may return the following error:
- status code 400, errno 123: unknown device
Not HAWK-authenticated.
Get 32 bytes of random data. This should be combined with locally-sourced entropy when creating salts, etc.
curl -X POST -v https://api-accounts.dev.lcip.org/v1/get_random_bytes
Successful requests will produce a "200 OK" response with the random bytes as hex-encoded data in the JSON body object:
{
"data": "ac55c0520f2edfb026761443da0ab27b1fa18c98912af6291714e9600aa34991"
}
There are no standard failure modes for this endpoint.
POST /get_random_bytes
POST /account/create
POST /account/login?keys=true
GET /recovery_email/status
POST /recovery_email/verify_code
GET /account/keys
POST /certificate/sign
POST /account/device
POST /account/login?keys=true
GET /account/keys
POST /certificate/sign
POST /account/device
POST /password/forgot/send_code
POST /password/forgot/verify_code
POST /account/reset
- GOTO "Attach a new device"
- start with active session (and keys)
POST /password/change/start
GET /account/keys
POST /password/change/finish
- GOTO "Attach a new device"
During periods of heavy load, the auth server may request that clients enter a "backoff" state in which they avoid making further requests.
If the server is under too much load to handle the client's request, it will return a 503 Service Unavailable
HTTP response. The response will include Retry-After
header giving the number of seconds that the client should wait before issuing any further requests. It will also include a JSON error response with errno
of 201, and with a retryAfter
field that matches the value in the Retry-After
header. For example, the following response would indicate that the server could not process the request and the client should avoid sending additional requests for 30 seconds:
HTTP/1.1 503 Service Unavailable
Retry-After: 30
Content-Type: application/json
{
"code": 503,
"errno": 201,
"error": "Service Unavailable",
"message": "The server is experiencing heavy load, please try again shortly",
"info": "https://github.com/mozilla/fxa-auth-server/blob/master/docs/api.md#response-format",
"retryAfter": 30
}
The Retry-After
value is included in both the headers and body so that clients can choose to handle it at the most appropriate level of abstraction for their environment.
If an individual client is found to be issuing too many requests in quick succession, the server may return a 429 Too Many Requests
response. This is similar to the 503 Service Unavailable
response but indicates that the problem originates from the client's behavior, rather than the server. The response will include Retry-After
header giving the number of seconds that the client should wait before issuing any further requests. It will also include a JSON error response with errno
of 114, and with a retryAfter
field that matches the value in the Retry-After
header. For example:
HTTP/1.1 429 Too Many Requests
Retry-After: 30
Content-Type: application/json
{
"code": 429,
"errno": 114,
"error": "Too Many Requests",
"message": "This client has sent too many requests",
"info": "https://github.com/mozilla/fxa-auth-server/blob/master/docs/api.md#response-format",
"retryAfter": 30
}