fxa-auth-server/docs/api.md

92 KiB

Firefox Accounts authentication server API

This document is automatically generated. If you are editing it, read this section first.

This document provides protocol-level details of the Firefox Accounts auth server API. For a prose description of the client/server protocol and details on how each parameter is derived, see the API design document. For a reference client implementation, see mozilla/fxa-js-client.

Overview

URL structure

All requests use URLs of the form:

https://<base-URI>/v1/<endpoint-path>

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 URI 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 https://api.accounts.firefox.com/v1.

Request format

Requests that require authentication use Hawk request signatures. These endpoints are marked with a 🔒 icon. Where the authentication is optional, there will also be a icon.

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 hexadecimal strings.

The following request headers may be specified to influence the behaviour of the server:

  • Accept-Language may be used to localize emails and SMS messages.

Response format

All requests receive a JSON response body with a Content-Type: application/json header and appropriate Content-Length set. The body structure depends on the endpoint returning it.

Successful responses will have an HTTP status code of 200 and a Timestamp header that contains the current server time in seconds since the epoch.

Error responses caused by invalid client behaviour will have an HTTP status code in the 4xx range. Error responses caused by server-side problems will have an HTTP status code in the 5xx range. Failures due to invalid behavior from the client

To simplify error handling for the client, the type of error is indicated by both a defined HTTP status code and an application-specific errno in the 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": "Invalid parameter in request body", // Specific error message
  "info": "https://docs.dev.lcip.og/errors/1234"  // Link to more information
}

Responses for some errors may include additional parameters.

Defined errors

The currently-defined values for code and errno are:

  • code: 400, errno: 100: Incorrect Database Patch Level
  • code: 400, errno: 101: Account already exists
  • code: 400, errno: 102: Unknown account
  • code: 400, errno: 103: Incorrect password
  • code: 400, errno: 104: Unverified account
  • code: 400, errno: 105: Invalid verification code
  • code: 400, errno: 106: Invalid JSON in request body
  • code: 400, errno: 107: Invalid parameter in request body
  • code: 400, errno: 108: Missing parameter in request body
  • code: 401, errno: 109: Invalid request signature
  • code: 401, errno: 110: Invalid authentication token in request signature
  • code: 401, errno: 111: Invalid timestamp in request signature
  • code: 411, errno: 112: Missing content-length header
  • code: 413, errno: 113: Request body too large
  • code: 429, errno: 114: Client has sent too many requests
  • code: 401, errno: 115: Invalid nonce in request signature
  • code: 410, errno: 116: This endpoint is no longer supported
  • code: 400, errno: 120: Incorrect email case
  • code: 400, errno: 123: Unknown device
  • code: 400, errno: 124: Session already registered by another device
  • code: 400, errno: 125: The request was blocked for security reasons
  • code: 400, errno: 126: Account must be reset
  • code: 400, errno: 127: Invalid unblock code
  • code: 400, errno: 129: Invalid phone number
  • code: 400, errno: 130: Invalid region
  • code: 400, errno: 131: Invalid message id
  • code: 500, errno: 132: Message rejected
  • code: 400, errno: 133: Email account sent complaint
  • code: 400, errno: 134: Email account hard bounced
  • code: 400, errno: 135: Email account soft bounced
  • code: 400, errno: 136: Email already exists
  • code: 400, errno: 137: Can not delete primary email
  • code: 400, errno: 138: Unverified session
  • code: 400, errno: 139: Can not add secondary email that is same as your primary
  • code: 400, errno: 140: Email already exists
  • code: 400, errno: 141: Email already exists
  • code: 400, errno: 142: Sign in with this email type is not currently supported
  • code: 400, errno: 143: Unknown email
  • code: 400, errno: 144: Email already exists
  • code: 400, errno: 145: Reset password with this email type is not currently supported
  • code: 400, errno: 146: Invalid signin code
  • code: 400, errno: 147: Can not change primary email to an unverified email
  • code: 400, errno: 148: Can not change primary email to an email that does not belong to this account
  • code: 400, errno: 149: This email can not currently be used to login
  • code: 400, errno: 150: Can not resend email code to an email that does not belong to this account
  • code: 400, errno: 151: Failed to send email
  • code: 400, errno: 152: Invalid token verification code
  • code: 400, errno: 153: Expired token verification code
  • code: 400, errno: 154: A TOTP token already exists for this account.
  • code: 400, errno: 155: A TOTP token not found.
  • code: 400, errno: 156: Recovery code not found.
  • code: 400, errno: 157: Unavailable device command.
  • code: 400, errno: 158: Recovery key not found.
  • code: 400, errno: 159: Recovery key is not valid.
  • code: 400, errno: 160: This request requires two step authentication enabled on your account.
  • code: 400, errno: 161: Recovery key already exists.
  • code: 503, errno: 201: Service unavailable
  • code: 503, errno: 202: Feature not enabled
  • code: 500, errno: 203: A backend service request failed.
  • code: 500, errno: 999: Unspecified error

The following errors include additional response properties:

  • errno: 100: level, levelRequired
  • errno: 101: email
  • errno: 102: email
  • errno: 103: email
  • errno: 105
  • errno: 107: validation
  • errno: 108: param
  • errno: 111: serverTime
  • errno: 114: retryAfter, retryAfterLocalized, verificationMethod, verificationReason
  • errno: 120: email
  • errno: 124: deviceId
  • errno: 125: verificationMethod, verificationReason
  • errno: 126: email
  • errno: 130: region
  • errno: 132: reason, reasonCode
  • errno: 133: bouncedAt
  • errno: 134: bouncedAt
  • errno: 135: bouncedAt
  • errno: 152
  • errno: 153
  • errno: 201: retryAfter
  • errno: 202: retryAfter
  • errno: 203: service, operation

Responses from intermediary servers

As with any HTTP-based API, clients must handle standard errors that may be returned by proxies, load-balancers or other intermediary servers. These non-application responses can be identified by the absence of a correctly-formatted JSON response body.

Common examples include:

  • 413 Request Entity Too Large: may be returned by an upstream proxy server.
  • 502 Gateway Timeout: may be returned if a load-balancer can't connect to application servers.

Validation

In the documentation that follows, some properties of requests and responses are validated by common code that has been refactored and extracted. For reference, those common validations are defined here.

lib/routes/validators

  • HEX_STRING: /^(?:[a-fA-F0-9]{2})+$/
  • BASE_36: /^[a-zA-Z0-9]*$/
  • URL_SAFE_BASE_64: /^[A-Za-z0-9_-]+$/
  • DISPLAY_SAFE_UNICODE: /^(?:[^\u0000-\u001F\u007F\u0080-\u009F\u2028-\u2029\uD800-\uDFFF\uE000-\uF8FF\uFFF9-\uFFFF])*$/
  • DISPLAY_SAFE_UNICODE_WITH_NON_BMP: /^(?:[^\u0000-\u001F\u007F\u0080-\u009F\u2028-\u2029\uE000-\uF8FF\uFFF9-\uFFFF])*$/
  • service: string, max(16), regex(/^[a-zA-Z0-9\-]*$/g)
  • verificationMethod: string, valid()
  • authPW: string, length(64), regex(HEX_STRING), required
  • wrapKb: string, length(64), regex(/^(?:[a-fA-F0-9]{2})+$/)
  • recoveryKeyId: string, regex(HEX_STRING), max(32)
  • recoveryData: string, regex(/[a-zA-Z0-9.]/), max(1024), required
  • E164_NUMBER: /^\+[1-9]\d{1,14}$/
  • DIGITS: /^[0-9]+$/
  • DEVICE_COMMAND_NAME: /^[a-zA-Z0-9._\/\-:]{1,100}$/
  • IP_ADDRESS: string, ip

lib/metrics/context

  • SCHEMA: object({

    • deviceId: string, length(32), regex(HEX_STRING), optional
    • flowId: string, length(64), regex(HEX_STRING), optional
    • flowBeginTime: number, integer, positive, optional
    • utmCampaign: string, optional
    • utmContent: string, optional
    • utmMedium: string, optional
    • utmSource: string, optional
    • utmTerm: string, optional

    }), unknown(false), and('flowId', 'flowBeginTime')

  • schema: SCHEMA.optional

  • requiredSchema: SCHEMA.required

lib/features

  • schema: array, items(string), optional

lib/devices

  • schema: {

    • id: isA.string.length(32).regex(HEX_STRING)
    • location: isA.object({
      • city: isA.string.optional.allow(null)
      • country: isA.string.optional.allow(null)
      • state: isA.string.optional.allow(null)
      • stateCode: isA.string.optional.allow(null)
      • })
    • name: isA.string.max(255).regex(DISPLAY_SAFE_UNICODE_WITH_NON_BMP)
    • nameResponse: isA.string.max(255)
    • type: isA.string.max(16)
    • pushCallback: validators.pushCallbackUrl({ scheme: 'https' }).regex(PUSH_SERVER_REGEX).max(255).allow('')
    • pushPublicKey: isA.string.max(88).regex(URL_SAFE_BASE_64).allow('')
    • pushAuthKey: isA.string.max(24).regex(URL_SAFE_BASE_64).allow('')
    • pushEndpointExpired: isA.boolean.strict
    • availableCommands: isA.object.pattern(validators.DEVICE_COMMAND_NAME
    • `isA.string.max(2048))

    }

API endpoints

Account

POST /account/create

Creates a user account. The client provides the email address with which this account will be associated 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 which service they are acting on behalf of. This is an opaque alphanumeric token that 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.

Query parameters
  • keys: boolean, optional

    Indicates whether a key-fetch token should be returned in the success response.

  • service: validators.service

    Opaque alphanumeric token to be included in verification links.

Request body
  • email: validators.email.required

    The primary email for this account.

  • authPW: validators.authPW

    The PBKDF2/HKDF-stretched password as a hex string.

  • preVerified: boolean

  • service: validators.service

    Opaque alphanumeric token to be included in verification links.

  • redirectTo: validators.redirectTo(config.smtp.redirectDomain).optional

    URL that the client should be redirected to after handling the request.

  • resume: string, max(2048), optional

    Opaque URL-encoded string to be included in the verification link as a query parameter.

  • metricsContext: metricsContext.schema

Response body
  • uid: string, regex(HEX_STRING), required

  • sessionToken: string, regex(HEX_STRING), required

  • keyFetchToken: string, regex(HEX_STRING), optional

  • authAt: number, integer

    Authentication time for the session (seconds since epoch).

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 400, errno: 101: Account already exists

  • code: 400, errno: 144: Email already exists

POST /account/login

Obtain a sessionToken and, optionally, a keyFetchToken if keys=true.

Query parameters
  • keys: boolean, optional

    Indicates whether a key-fetch token should be returned in the success response.

  • service: validators.service

    Opaque alphanumeric token to be included in verification links.

  • verificationMethod: validators.verificationMethod.optional

    If this param is specified, it forces the login to be verified using the specified method.

    Currently supported methods:

    • email
      • Sends an email with a confirmation link.
    • email-2fa
      • Sends an email with a confirmation code.
    • email-captcha
      • Sends an email with an unblock code.
Request body
  • email: validators.email.required

    The primary email for this account.

  • authPW: validators.authPW

    The PBKDF2/HKDF stretched password as a hex string.

  • service: validators.service

    Opaque alphanumeric token to be included in verification links.

  • redirectTo: validators.redirectTo(config.smtp.redirectDomain).optional

  • resume: string, optional

    Opaque URL-encoded string to be included in the verification link as a query parameter.

  • reason: string, max(16), optional

    Alphanumeric string indicating the reason for establishing a new session; may be "login" (the default) or "reconnect".

  • unblockCode: signinUtils.validators.UNBLOCK_CODE

    Alphanumeric code used to unblock certain rate-limitings.

  • metricsContext: metricsContext.schema

  • originalLoginEmail: validators.email.optional

    This parameter is the original email used to login with. Typically, it is specified after a user logins with a different email case, or changed their primary email address.

  • verificationMethod: validators.verificationMethod.optional

    If this param is specified, it forces the login to be verified using the specified method.

    Currently supported methods:

    • email
      • Sends an email with a confirmation link.
    • email-2fa
      • Sends an email with a confirmation code.
    • email-captcha
      • Sends an email with an unblock code.
Response body
  • uid: string, regex(HEX_STRING), required

  • sessionToken: string, regex(HEX_STRING), required

  • keyFetchToken: string, regex(HEX_STRING), optional

  • verificationMethod: string, optional

    The medium for how the user can verify.

  • verificationReason: string, optional

    The authentication method that required additional verification.

  • verified: boolean, required

  • authAt: number, integer

    Authentication time for the session (seconds since epoch).

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 400, errno: 102: Unknown account

  • code: 400, errno: 103: Incorrect password

  • code: 400, errno: 125: The request was blocked for security reasons

  • code: 400, errno: 127: Invalid unblock code

  • code: 400, errno: 142: Sign in with this email type is not currently supported

  • code: 400, errno: 149: This email can not currently be used to login

  • code: 400, errno: 160: This request requires two step authentication enabled on your account.

GET /account/status

🔒🔓 Optionally HAWK-authenticated with session token

Gets the status of an account.

Query parameters
  • uid: string, min(32), max(32), regex(validators.HEX_STRING)

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 400, errno: 108: Missing parameter in request body

POST /account/status

Gets the status of an account without exposing user data through query params. This endpoint is rate limited by fxa-customs-server.

Request body
  • email: validators.email.required

Response body
  • exists: boolean, required

GET /account/profile

🔒 authenticated with OAuth bearer token, or HAWK-authenticated with session token

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 requires profile:email scope.

  • locale requires profile:locale scope.

  • authenticationMethods and authenticatorAssuranceLevel require profile:amr scope.

The profile scope includes all the above sub-scopes.

Response body
  • email: string, optional

  • locale: string, optional, allow(null)

  • authenticationMethods: array, items(string, required), optional

  • authenticatorAssuranceLevel: number, min(0)

GET /account/keys

🔒 HAWK-authenticated with key fetch token

Get the base-16 bundle of encrypted kA|wrapKb. The return value must be decrypted with a key derived from keyFetchToken, 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 keyFetchToken is consumed regardless of whether the request succeeds or fails.

This request will fail unless the account's email address and current session has been verified.

Response body
  • bundle: string, regex(validators.HEX_STRING)

    See decrypting the bundle for information on how to extract kA|wrapKb from the bundle.

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 400, errno: 104: Unverified account

POST /account/unlock/resend_code

This endpoint is deprecated.

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 410, errno: 116: This endpoint is no longer supported

POST /account/unlock/verify_code

This endpoint is deprecated.

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 410, errno: 116: This endpoint is no longer supported

POST /account/reset

🔒 HAWK-authenticated with account reset token

This sets the account password and resets wrapKb to a new random value.

Account reset tokens are single-use and consumed regardless of whether the request succeeds or fails. They are returned by the POST /password/forgot/verify_code endpoint.

The caller can optionally request a new sessionToken and keyFetchToken.

Query parameters
  • keys: boolean, optional

    Indicates whether a new keyFetchToken is required, default to false.

Request body
  • authPW: validators.authPW

    The PBKDF2/HKDF-stretched password as a hex string.

  • wrapKb: validators.wrapKb.optional

  • recoveryKeyId: validators.recoveryKeyId.optional

  • sessionToken: boolean, optional

    Indicates whether a new sessionToken is required, default to false.

  • metricsContext: metricsContext.schema

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 400, errno: 108: Missing parameter in request body

POST /account/destroy

🔒🔓 Optionally HAWK-authenticated with session token

Deletes an account. 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.

Request body
  • email: validators.email.required

    Primary email address of the account.

  • authPW: validators.authPW

    The PBKDF2/HKDF-stretched password as a hex string.

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 400, errno: 103: Incorrect password

  • code: 400, errno: 138: Unverified session

Devices and sessions

POST /account/device

🔒 HAWK-authenticated with session token

Either:

  • Registers a new device for this session if no device id is specified, or;

  • Updates existing device details for this 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 or the tuple { pushCallback, pushPublicKey, pushAuthKey } must be present. Beware that if you provide pushCallback without the pair { pushPublicKey, pushAuthKey }, both of those keys will be reset to the empty string.

pushEndpointExpired will be reset to false on update if the tuple { pushCallback, pushPublicKey, pushAuthKey } is specified.

Devices should register with this endpoint before attempting to obtain a signed certificate and perform their first sync, so that an appropriate device name can be made available to other connected devices.

Request body
  • id: DEVICES_SCHEMA.id.required

  • name: DEVICES_SCHEMA.name.optional;
    or DEVICES_SCHEMA.name.required

  • type: DEVICES_SCHEMA.type.optional;
    or DEVICES_SCHEMA.type.required

  • pushCallback: DEVICES_SCHEMA.pushCallback.optional

  • pushPublicKey: DEVICES_SCHEMA.pushPublicKey.optional

  • pushAuthKey: DEVICES_SCHEMA.pushAuthKey.optional

  • availableCommands: DEVICES_SCHEMA.availableCommands.optional

  • capabilities: array, length(0), optional

Response body
  • id: DEVICES_SCHEMA.id.required

  • createdAt: number, positive, optional

  • name: DEVICES_SCHEMA.nameResponse.optional

  • type: DEVICES_SCHEMA.type.optional

  • pushCallback: DEVICES_SCHEMA.pushCallback.optional

  • pushPublicKey: DEVICES_SCHEMA.pushPublicKey.optional

  • pushAuthKey: DEVICES_SCHEMA.pushAuthKey.optional

  • pushEndpointExpired: DEVICES_SCHEMA.pushEndpointExpired.optional

  • availableCommands: DEVICES_SCHEMA.availableCommands.optional

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 400, errno: 107: Invalid parameter in request body

  • code: 503, errno: 202: Feature not enabled

GET /account/device/commands

🔒 HAWK-authenticated with session token

Fetches commands enqueued for the current device by prior calls to /account/devices/invoke_command. The device can page through the enqueued commands by using the index and limit parameters.

For more details, see the device registration docs.

Query parameters
  • index: number, optional

    The index of the most recently seen command item. Only commands enqueued after the given index will be returned.

  • limit: number, optional, min(0), max(100), default(100)

    The maximum number of commands to return. The default and maximum value for limit is 100.

Response body
  • index: number, required

    The largest index of the commands returned in this response. This value can be passed as the index parameter in subsequent calls in order to page through all the items.

  • last: boolean, optional

    Indicates whether more commands and enqueued than could be returned within the specific limit.

  • messages: array, items(object({ index: number, required, data: object({ command: string, max(255), required, payload: object, required, sender: DEVICES_SCHEMA.id, optional }), required })), optional

    An array of individual commands for the device to process.

POST /account/devices/invoke_command

🔒 HAWK-authenticated with session token

Enqueues a command to be invoked on a target device.

For more details, see the device registration docs.

Request body
  • target: DEVICES_SCHEMA.id.required

    The id of the device on which to invoke the command.

  • command: string, required

    The id of the command to be invoked, as found in the device's availableCommands set.

  • payload: object, required

    Opaque payload to be forwarded to the device.

  • ttl: number, integer, min(0), max(10000000), optional

    The time in milliseconds after which the command should expire, if not processed by the device.

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 400, errno: 157: Unavailable device command.

POST /account/devices/notify

🔒 HAWK-authenticated with session token

Notifies a set of devices associated with the user's account of an event by sending a browser push notification. A typical use case would be to send a notification to another device after sending a tab with Sync, so it can sync too and display the tab in a timely manner.

Request body
  • to: string, valid('all'), required;
    or array, items(string, length(32), regex(HEX_STRING)), required

    Devices to notify. May be the string 'all' or an array containing the relevant device ids.

  • _endpointAction: string, valid('accountVerify'), optional

  • excluded: array, items(string, length(32), regex(HEX_STRING)), optional

    Array of device ids to exclude from the notification. Ignored unless to:"all" is specified.

  • payload: object, when('_endpointAction', { is: 'accountVerify', then: required, otherwise: required })

    Push payload, validated against pushpayloads.schema.json.

  • TTL: number, integer, min(0), optional

    Push notification TTL, defaults to 0.

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 400, errno: 107: Invalid parameter in request body

  • code: 503, errno: 202: Feature not enabled

GET /account/devices

🔒 HAWK-authenticated with session token

Returns an array of registered device objects for the authenticated user.

Response body
  • id: DEVICES_SCHEMA.id.required

  • isCurrentDevice: boolean, required

  • lastAccessTime: number, min(0), required, allow(null)

  • lastAccessTimeFormatted: string, optional, allow('')

  • approximateLastAccessTime: number, min(earliestSaneTimestamp), optional

  • approximateLastAccessTimeFormatted: string, optional, allow('')

  • location: DEVICES_SCHEMA.location

  • name: DEVICES_SCHEMA.nameResponse.allow('').required

  • type: DEVICES_SCHEMA.type.required

  • pushCallback: DEVICES_SCHEMA.pushCallback.allow(null).optional

  • pushPublicKey: DEVICES_SCHEMA.pushPublicKey.allow(null).optional

  • pushAuthKey: DEVICES_SCHEMA.pushAuthKey.allow(null).optional

  • pushEndpointExpired: DEVICES_SCHEMA.pushEndpointExpired.optional

  • availableCommands: DEVICES_SCHEMA.availableCommands.optional

GET /account/sessions

🔒 HAWK-authenticated with session token

Returns an array of session objects for the authenticated user.

Response body
  • id: string, regex(HEX_STRING), required

  • lastAccessTime: number, min(0), required, allow(null)

  • lastAccessTimeFormatted: string, optional, allow('')

  • approximateLastAccessTime: number, min(earliestSaneTimestamp), optional

  • approximateLastAccessTimeFormatted: string, optional, allow('')

  • createdTime: number, min(0), required, allow(null)

  • createdTimeFormatted: string, optional, allow('')

  • location: DEVICES_SCHEMA.location

    Object containing the client's state and country

  • userAgent: string, max(255), required, allow('')

  • os: string, max(255), allow(''), allow(null)

  • deviceId: DEVICES_SCHEMA.id.allow(null).required

  • deviceName: DEVICES_SCHEMA.nameResponse.allow('').allow(null).required

  • deviceAvailableCommands: DEVICES_SCHEMA.availableCommands.allow(null).required

  • deviceType: DEVICES_SCHEMA.type.allow(null).required

  • deviceCallbackURL: DEVICES_SCHEMA.pushCallback.allow(null).required

  • deviceCallbackPublicKey: DEVICES_SCHEMA.pushPublicKey.allow(null).required

  • deviceCallbackAuthKey: DEVICES_SCHEMA.pushAuthKey.allow(null).required

  • deviceCallbackIsExpired: DEVICES_SCHEMA.pushEndpointExpired.allow(null).required

  • isDevice: boolean, required

  • isCurrentDevice: boolean, required

POST /account/device/destroy

🔒 HAWK-authenticated with session token

Destroys a device record and the associated sessionToken for the authenticated user. The identified device must sign in again to use the API after this request has succeeded.

Request body
  • id: DEVICES_SCHEMA.id.required

Emails

GET /recovery_email/status

🔒 HAWK-authenticated with session token

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, POST /certificate/sign and GET /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 account. During account creation, until the address is verified, the agent can poll this method to discover when it should proceed with POST /certificate/sign and GET /account/keys.

Query parameters
  • reason: string, max(16), optional

Response body
  • email: string, required

  • verified: boolean, required

  • sessionVerified: boolean, optional

  • emailVerified: boolean, optional

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 401, errno: 110: Invalid authentication token in request signature

POST /recovery_email/resend_code

🔒 HAWK-authenticated with session token

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 via 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, 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're acting on behalf of. This is an opaque alphanumeric token that will be embedded in the verification link as a query parameter.

Query parameters
  • service: validators.service

    Opaque alphanumeric token to be included in verification links.

  • type: string, max(32), alphanum, allow(), optional

Request body
  • email: validators.email.optional

  • service: validators.service

    Opaque alphanumeric token to be included in verification links.

  • redirectTo: validators.redirectTo(config.smtp.redirectDomain).optional

  • resume: string, max(2048), optional

    Opaque URL-encoded string to be included in the verification link as a query parameter.

  • metricsContext: metricsContext.schema

  • type: string, max(32), alphanum, allow(), optional

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 400, errno: 150: Can not resend email code to an email that does not belong to this account

POST /recovery_email/verify_code

Verify tokens and/or recovery emails for an account. If a valid token code is detected, the account email and tokens will be set to verified. If a valid email code is detected, the email will be marked as verified.

The verification code will be a random token, delivered in the fragment identifier of a URL sent to the user's email address. Navigating to the URL opens a page that extracts the code from the fragment identifier 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.

Query parameters
  • service: validators.service

    Opaque alphanumeric token to be included in verification links.

  • reminder: string, max(32), alphanum, optional

    Deprecated.

  • type: string, max(32), alphanum, optional

    The type of code being verified.

Request body
  • uid: string, max(32), regex(HEX_STRING), required

  • code: string, min(32), max(32), regex(HEX_STRING), required

  • service: validators.service

    Opaque alphanumeric token to be included in verification links.

  • reminder: string, max(32), alphanum, optional

    Deprecated.

  • type: string, max(32), alphanum, optional

    The type of code being verified.

  • marketingOptIn: boolean

    Set to true if the user has opted-in to our marketing. When verified, the auth-server will notify Basket.

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 400, errno: 105: Invalid verification code

GET /recovery_emails

🔒 HAWK-authenticated with session token

Returns an array of objects containing details of the email addresses associated with the logged-in user. Currently, the primary email address is always the one from the accounts table.

Response body
  • verified: boolean, required

  • isPrimary: boolean, required

  • email: validators.email.required

POST /recovery_email

🔒 HAWK-authenticated with session token

Add a secondary email address to the logged-in account. The created address will be unverified and will not replace the primary email address.

Request body
  • email: validators.email.required

    The email address to add to the account.

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 400, errno: 104: Unverified account

  • code: 400, errno: 138: Unverified session

  • code: 400, errno: 139: Can not add secondary email that is same as your primary

  • code: 400, errno: 140: Email already exists

  • code: 400, errno: 141: Email already exists

  • code: 400, errno: 151: Failed to send email

POST /recovery_email/destroy

🔒 HAWK-authenticated with session token

Delete an email address associated with the logged-in user.

Request body
  • email: validators.email.required

    The email address to delete.

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 400, errno: 138: Unverified session

POST /recovery_email/set_primary

🔒 HAWK-authenticated with session token

This endpoint changes a user's primary email address. This email address must belong to the user and be verified.

Request body
  • email: validators.email.required

    The new primary email address of the user.

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 400, errno: 138: Unverified session

  • code: 400, errno: 147: Can not change primary email to an unverified email

  • code: 400, errno: 148: Can not change primary email to an email that does not belong to this account

Password

POST /password/change/start

Begin the "change password" process. Returns a single-use passwordChangeToken, to be sent to POST /password/change/finish. Also returns a single-use keyFetchToken.

Request body
  • email: validators.email.required

    Primary email address of the account.

  • oldAuthPW: validators.authPW

    The PBKDF2/HKDF-stretched password as a hex string.

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 400, errno: 103: Incorrect password

POST /password/change/finish

🔒 HAWK-authenticated with password change token

Change the password and update wrapKb. Optionally returns sessionToken and keyFetchToken.

Query parameters
  • keys: boolean, optional

    Indicates whether a new keyFetchToken is required, default to false.

Request body
  • authPW: validators.authPW

    The PBKDF2/HKDF-stretched password as a hex string.

  • wrapKb: validators.wrapKb

    The new wrapKb value as a hex string.

  • sessionToken: string, min(64), max(64), regex(HEX_STRING), optional

    Indicates whether a new sessionToken is required, default to false.

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 400, errno: 138: Unverified session

POST /password/forgot/send_code

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 POST /password/forgot/verify_code.

The code will be either 8 or 16 digits long, with the length indicated in the response. The email will either contain the code itself or the URL for a web page that displays the code.

The response includes passwordForgotToken, which must be submitted with the code to POST /password/forgot/verify_code.

The response also specifies the TTL of passwordForgotToken and an upper limit on the number of times the token may be submitted. 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 has been made, the agent must call this endpoint again to generate a new code and token pair.

Each account can have at most one passwordForgotToken valid at a time. Calling this endpoint causes existing tokens to be invalidated and a new one created. Each token is associated with a specific code, so by extension the codes are invalidated with their tokens.

Query parameters
  • service: validators.service

    Identifies the relying service the user was interacting with that triggered the password reset.

  • keys: boolean, optional

Request body
  • email: validators.email.required

    Recovery email for the account.

  • service: validators.service

    Identifies the relying service the user was interacting with that triggered the password reset.

  • redirectTo: validators.redirectTo(redirectDomain).optional

    URL that the client should be redirected to after handling the request.

  • resume: string, max(2048), optional

    Opaque URL-encoded string to be included in the verification link as a query parameter.

  • metricsContext: metricsContext.schema

Response body
  • passwordForgotToken: string

  • ttl: number

  • codeLength: number

  • tries: number

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 400, errno: 145: Reset password with this email type is not currently supported

POST /password/forgot/resend_code

🔒 HAWK-authenticated with password forgot token

Resends the email from POST /password/forgot/send_code, for use when the original email has been lost or accidentally deleted.

This endpoint requires the passwordForgotToken returned in the original response, so only the original client which started the process may request a resent message. The response will match that from POST /password/forgot/send_code, except ttl will be lower to indicate the shorter validity period. tries will also be lower if POST /password/forgot/verify_code has been called.

Query parameters
  • service: validators.service

    Identifies the relying service the user was interacting with that triggered the password reset.

Request body
  • email: validators.email.required

    Recovery email for the account.

  • service: validators.service

    Identifies the relying service the user was interacting with that triggered the password reset.

  • redirectTo: validators.redirectTo(redirectDomain).optional

    URL that the client should be redirected to after handling the request.

  • resume: string, max(2048), optional

    Opaque URL-encoded string to be included in the verification link as a query parameter.

  • metricsContext: metricsContext.schema

Response body
  • passwordForgotToken: string

  • ttl: number

  • codeLength: number

  • tries: number

POST /password/forgot/verify_code

🔒 HAWK-authenticated with password forgot token

The code returned by POST /v1/password/forgot/send_code should be submitted to this endpoint with the passwordForgotToken. For successful requests, the server will return accountResetToken, to be submitted in requests to POST /account/reset to reset the account password and wrapKb.

Request body
  • code: string, min(32), max(32), regex(HEX_STRING), required

    The code sent to the user's recovery email.

  • metricsContext: metricsContext.schema

  • accountResetWithRecoveryKey: boolean, optional

Response body
  • accountResetToken: string

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 400, errno: 105: Invalid verification code

GET /password/forgot/status

🔒 HAWK-authenticated with password forgot token

Returns the status of a passwordForgotToken. Success responses indicate the token has not yet been consumed. For consumed or expired tokens, an HTTP 401 response with errno: 110 will be returned.

Response body
  • tries: number

  • ttl: number

Recovery codes

GET /recoveryCodes

🔒 HAWK-authenticated with session token

Return new recovery codes while removing old ones.

Response body
  • recoveryCodes: array, items(string)

POST /session/verify/recoveryCode

🔒 HAWK-authenticated with session token

Verify a session using a recovery code.

Request body
  • code: string, max(RECOVERY_CODE_SANE_MAX_LENGTH), regex(BASE_36), required

  • metricsContext: metricsContext.schema

Response body
  • remaining: number

Recovery key

POST /recoveryKey

🔒 HAWK-authenticated with session token

Creates a new recovery key for a user.

Recovery keys are one-time-use tokens that can be used to recover the user's kB if they forget their password. For more details, see the recovery keys docs.

Request body
  • recoveryKeyId: validators.recoveryKeyId

    A unique identifier for this recovery key, derived from the key via HKDF.

  • recoveryData: validators.recoveryData

    An encrypted bundle containing the user's kB.

GET /recoveryKey/{recoveryKeyId}

🔒 HAWK-authenticated with account reset token

Retrieve the account recovery data associated with the given recovery key.

POST /recoveryKey/exists

🔒🔓 Optionally HAWK-authenticated with session token

This route checks to see if given user has setup an account recovery key. When used during the password reset flow, an email can be provided (instead of a sessionToken) to check for the status. However, when using an email, the request is rate limited.

Request body
  • email: validators.email.optional

Response body
  • exists: boolean, required

DELETE /recoveryKey

🔒 HAWK-authenticated with session token

This route remove an account's recovery key. When the key is removed, it can no longer be used to restore an account's kB.

Session

POST /session/destroy

🔒 HAWK-authenticated with session token

Destroys the current session and invalidates sessionToken, to be called when a user signs out. To sign back in, a call must be made to POST /account/login to obtain a new sessionToken.

Request body
  • customSessionToken: string, min(64), max(64), regex(HEX_STRING), optional

    Custom session token id to destroy.

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 401, errno: 110: Invalid authentication token in request signature

POST /session/reauth

🔒 HAWK-authenticated with session token

Re-authenticate an existing session token. This is equivalent to calling /account/login, but it re-uses an existing session token rather than generating a new one, allowing the caller to maintain session state such as verification and device registration.

Query parameters
  • keys: boolean, optional

  • service: validators.service

  • verificationMethod: validators.verificationMethod.optional

Request body
  • email: validators.email.required

  • authPW: validators.authPW

  • service: validators.service

  • redirectTo: validators.redirectTo(config.smtp.redirectDomain).optional

  • resume: string, optional

  • reason: string, max(16), optional

  • unblockCode: signinUtils.validators.UNBLOCK_CODE

  • metricsContext: metricsContext.schema

  • originalLoginEmail: validators.email.optional

  • verificationMethod: validators.verificationMethod.optional

Response body
  • uid: string, regex(HEX_STRING), required

  • keyFetchToken: string, regex(HEX_STRING), optional

  • verificationMethod: string, optional

  • verificationReason: string, optional

  • verified: boolean, required

  • authAt: number, integer

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 400, errno: 102: Unknown account

  • code: 400, errno: 103: Incorrect password

  • code: 400, errno: 125: The request was blocked for security reasons

  • code: 400, errno: 127: Invalid unblock code

  • code: 400, errno: 142: Sign in with this email type is not currently supported

  • code: 400, errno: 149: This email can not currently be used to login

  • code: 400, errno: 160: This request requires two step authentication enabled on your account.

GET /session/status

🔒 HAWK-authenticated with session token

Returns a success response if the session token is valid.

Response body
  • state: string, required

  • uid: string, regex(HEX_STRING), required

POST /session/duplicate

🔒 HAWK-authenticated with session token

Create a new sessionToken that duplicates the current session. It will have the same verification status as the current session, but will have a distinct verification code.

Request body
  • reason: string, max(16), optional

Sign

POST /certificate/sign

🔒 HAWK-authenticated with session token

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 browserid-certifier 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 primary email address for the account has been verified.

Clients should include a query parameter, service, for metrics and validation purposes. The value of service should be sync when connecting to Firefox Sync or the OAuth client_id when connecting to an OAuth relier.

If you do not specify a service parameter, or if you specify service=sync, this endpoint assumes the request is from a legacy Sync client. If the session token doesn't have a corresponding device record, one will be created automatically by the server.

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, in seconds since epoch.

  • fxa-verifiedEmail: The user's verified recovery email address.

Query parameters
  • service: validators.service

Request body
  • publicKey: object({ algorithm: string, valid('RS', 'DS'), required, n: string, e: string, y: string, p: string, q: string, g: string, version: string }), required

    The key to sign (run bin/generate-keypair from browserid-crypto).

  • duration: number, integer, min(0), max(), required

    Time interval in milliseconds until the certificate will expire, up to a maximum of 24 hours.

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 400, errno: 104: Unverified account

  • code: 400, errno: 108: Missing parameter in request body

  • code: 400, errno: 138: Unverified session

Signin codes

POST /signinCodes/consume

Exchange a single-use signin code for an email address.

Request body
  • code: string, regex(validators.URL_SAFE_BASE_64), required

    The signin code.

  • metricsContext: metricsContext.requiredSchema

    Metrics context data for the new flow.

Response body
  • email: validators.email.required

    The email address associated with the signin code.

Sms

POST /sms

🔒 HAWK-authenticated with session token

Sends an SMS message.

Request body
  • phoneNumber: string, regex(validators.E164_NUMBER), required

    The phone number to send the message to, in E.164 format.

  • messageId: number, positive, required

    The id of the message to send.

  • metricsContext: metricsContext.schema

    Metrics context data for the request.

  • features: features.schema

    Enabled features for the request.

Error responses

Failing requests may be caused by the following errors (this is not an exhaustive list):

  • code: 400, errno: 129: Invalid phone number

  • code: 400, errno: 130: Invalid region

GET /sms/status

🔒 HAWK-authenticated with session token

Returns SMS status for the current user.

Query parameters
  • country: string, regex(/^[A-Z][A-Z]$/), optional

    Skip geo-lookup and act as if the user is in the specified country.

Token codes

POST /session/verify/token

🔒 HAWK-authenticated with session token

Verify a session using a token code.

Request body
  • code: string, min(TOKEN_CODE_LENGTH), max(TOKEN_CODE_LENGTH), regex(DIGITS), required

    The code

  • uid: string, max(32), regex(HEX_STRING), optional

    The uid associated with the token code

Totp

POST /totp/create

🔒 HAWK-authenticated with session token

Create a new randomly generated TOTP token for a user if they do not currently have one.

Request body
  • metricsContext: metricsContext.schema

POST /totp/destroy

🔒 HAWK-authenticated with session token

Deletes the current TOTP token for the user.

GET /totp/exists

🔒 HAWK-authenticated with session token

Checks to see if the user has a TOTP token.

POST /session/verify/totp

🔒 HAWK-authenticated with session token

Verifies the current session if the passed TOTP code is valid.

Request body
  • code: string, max(32), regex(validators.DIGITS), required

    The TOTP code to check

  • metricsContext: metricsContext.schema

  • service: validators.service

Response body
  • success: boolean, required

  • recoveryCodes: array, items(string), optional

Unblock codes

POST /account/login/send_unblock_code

Send an unblock code via email to reset rate-limiting for an account.

Request body
  • email: validators.email.required

    Primary email for the account.

  • metricsContext: metricsContext.schema

POST /account/login/reject_unblock_code

Used to reject and report unblock codes that were not requested by the user.

Request body
  • uid: string, max(32), regex(HEX_STRING), required

    The user id.

  • unblockCode: string, regex(BASE_36), length(unblockCodeLen), required

    The unblock code.

Util

POST /get_random_bytes

Get 32 bytes of random data. This should be combined with locally-sourced entropy when creating salts, etc.

GET /verify_email

Query parameters
  • code: string, max(32), regex(HEX_STRING), required

  • uid: string, max(32), regex(HEX_STRING), required

  • service: string, max(16), alphanum, optional

  • redirectTo: validators.redirectTo(redirectDomain).optional

GET /complete_reset_password

Query parameters
  • email: validators.email.required

  • code: string, max(32), regex(HEX_STRING), required

  • token: string, max(64), regex(HEX_STRING), required

  • service: string, max(16), alphanum, optional

  • redirectTo: validators.redirectTo(redirectDomain).optional

Back-off protocol

During periods of heavy load, the server may request that clients enter a "back-off" state, in which they avoid making further requests.

At such times, it will return a 503 Service Unavailable response with a Retry-After header denoting the number of seconds to wait before issuing any further requests. It will also include errno: 201 and a retryAfter field matching the value of the Retry-After header in the body.

For example, the following response indicates that the client should suspend making further 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": "Service unavailable",
  "info": "https://github.com/mozilla/fxa-auth-server/blob/master/docs/api.md#response-format",
  "retryAfter": 30,
  "retryAfterLocalized": "in a few seconds"
}

This document

This document is automatically generated by a script that parses the source code and the document itself.

All changes to this document will be lost unless they are made inside delimiting HTML comments of the form:

<!--begin-foo-bar-->
YOUR CHANGE GOES HERE
<!--end-foo-bar->

foo-bar must be a tag that, when camel-cased, matches a property name in the data for the mustache template this document is generated from.

If you want to change the structure of the document, you must make your changes to scripts/api-docs.mustache rather than in this document directly.