The Firefox Accounts server provides a shared authentication and management infrastructure for the Mozilla Cloud Services ecosystem. It is a HTTP API through which a user-agent can manage:
- user account details, such as email address and password
- the list of devices connected to the account
- the master encryption keys used by services connected to the account
There is no UI provided by this server. It is expected that user interaction will happen through Firefox or a hosted website, which will use the API provided by this server.
Each user of the service creates an account which has a unique id. Access to the account is authenticated by an email/password pair and uses the Secure Remote Password protocol to avoid revealing the password to the server. Note that our SRP protocol ordering is slightly different from the sample on wikipedia, but the variables are the same.
The user connects one or more devices to their account. Each device performs the SRP authentication protocol to obtain one or more opaque authentication tokens, which are then used to make Hawk signed requests when interacting with the server API. This token exchange means the device does not need to keep the the user's password in persistent storage.
Once connected, each device can fetch the user's encryption keys. The server maintains two keys for each account, called kA and kB. kA is known to the server, and is intended for encrypting data that must be recoverable in the event of password reset. kB is stored encrypted by the user's password, and is intended for more secure encryption at the cost of unrecoverability when the password is forgotten.
All server functionality is exposed via a HTTP API. It is JSON based and vaguely restful. A detailed description is available here and a prose overview of the design and cryptogaphic details is available here.
Run lint with:
yarn lint
Linting will also be run for staged files automatically via Husky when you attempt to commit.
Before running tests make sure the correct services are running. If auth server is running in pm2 weird behavior can ensue, so
prior to running tests we recommend creating a clean slate by running yarn stop.
Now we can start testing. To run unit tests:
nx test-unit fxa-auth-serverNote this matches how auth server unit tests jobs in CI.
To run integration tests, we have to make sure databases and auxillary services required for integration testing are spun up. So run:
yarn start infrastructurenx start fxa-customs-server
Now integration tests can be executed:
nx test-integration fxa-auth-serverNote this matches how auth server unit tests jobs in CI.
For general development based testing, specific tests can be targeted using Jest:
From packages/fxa-auth-server:
npx jest --forceExit lib/routes/account.spec.tsnpx jest --forceExit --testPathPattern 'lib/routes/.*spec'npx jest --forceExit -t "SQSReceiver"
Notes / Tips:
- For quick environment config, consider running tests with a .env file and the dotenv command. For example:
dotenv -- yarn workspace fxa-auth-server:test-integration remote - You can use
LOG_LEVEL, such asLOG_LEVEL=debugto specify the test logging level. - Recovery-phone tests require twilio testing credentials!
- Recovery-phone-customs tests require that customs server is running. So run
nx start fxa-customs-serverprior to executing tests. - The test/remote folder contains integration tests that are not designed to be run in parallel. Use
yarn test-integrationinstead of running them directly.
Executing tests using remote databases (MySQL, Redis) is possible by specifying (and exporting) the following environment variables:
- MySQL:
- MYSQL_HOST
- MYSQL_SLAVE_HOST
- AUTH_MYSQL_HOST
- Redis:
- REDIS_HOST
- ACCESS_TOKEN_REDIS_HOST
- REFRESH_TOKEN_REDIS_HOST
- METRICS_REDIS_HOST
This also allows to use temporary throw-away Docker containers to provide these.
See the "Emails" page in ecosystem platform for docs on our email stack, including styling and l10n guides.
Storybook is set up in the auth-server for FxA and SubPlat emails. See our "emails" documentation for more info.
Strings are automatically extracted to the fxa-content-server-l10n repo where they reach Pontoon for translations to occur by our l10n team and contributors. This is achieved by concatenating all of our .ftl (Fluent) files into a single auth.ftl file with the merge-ftl grunttask, and the extract-and-pull-request.sh script that runs in fxa-content-server-l10n on a weekly cadence. For more detailed information, check out the ecosystem platform l10n doc.
Brands we have set to message references are stored in libs/shared/l10n/src/lib/branding.ftl. Non-email strings that must be translated are placed directly in lib/l10n/server.ftl. Email strings for translation are placed in a nearby (templates/[templateName]/en.ftl or partials/[partialName]/en.ftl). For more detailed information on l10n in emails with examples, see the ecosystem platform doc email page, l10n section.
Use the FXA_L10N_SHA to pin L10N files to certain SHA. If not set then the master SHA will be used.
Configuration of this project
is managed by convict,
using the schema in
config/index.ts.
Default values from this schema can be overridden in two ways:
-
By setting individual environment variables, as indicated by the
envproperty for each item in the schema.For example:
export CONTENT_SERVER_URL="http://your.content.server.org"
-
By specifying the path to a conforming JSON file, or a comma-separated list of paths, using the
CONFIG_FILESenvironment variable. Files specified in this way are loaded when the server starts. If the server fails to start, it usually indicates that one of these JSON files does not conform to the schema; check the error message for more information.For example:
export CONFIG_FILES="~/fxa-content-server.json,~/fxa-db.json"
Rate-limiting and blocking is handled by fxa-customs-server. By default, these policies are disabled in dev environment via "customsUrl":"none" in fxa-auth-server/config/dev.json. Enabling the customs server allows error messages to be displayed when rate limiting occurs. Default rate-limiting values are found in fxa-customs-server/lib/config/config.js and can be modified with environment variables or by adding a dev.json file to fxa-customs-server/config/.
The customs-server can be enabled for local testing by changing the dev config to "customsUrl":"http://localhost:7000".
Recovery phone uses twilio to send SMS. Twilio has two different modes it can operate in based on the credentials provided.
There is a 'test' mode and a 'default' mode. The testing mode cannot send messages to real phone numbers, but it can send messages to 'magic' testing numbers that are reserved and maintained by Twilio for testing purposes and are free to send SMS to. The default mode can send out real messages, but cannot send messages to 'magic' testing numbers. These credentials can be obtained by going to twilio.com logging into your account, and finding them in the testing console. If you are new to the FxA team, contact a team member to get twilio access.
The 'test' mode can send SMS to magic test numbers at no cost. This is what we use for unit/integration testing.
The 'default' mode can send SMS to real numbers, but will incur const, and cannot send messages to magic test numbers. This is what we use for manual testing.
To make switching between these modes easy, we've created the twilio.credentialMode configuration setting. Simply set the
apiKeys and testCredentials, then toggle credentialMode from test to apiKeys depending on how you are testing. Here's a
snippet from .env that shows an example of this.
RECOVERY_PHONE__ENABLED=true
RECOVERY_PHONE__TWILIO__ACCOUNT_SID=######
# Set apiKeys for manual testing
RECOVERY_PHONE__TWILIO__API_KEY=######
RECOVERY_PHONE__TWILIO__API_SECRET=######
# These are the specific Twilio test credentials that allow us to send out sms to
# magic numbers and incur no cost. Set these so we can run our automated tests.
RECOVERY_PHONE__TWILIO__TEST_ACCOUNT_SID=######
RECOVERY_PHONE__TWILIO__TEST_AUTH_TOKEN=######
# Important! Toggle this value between 'apiKeys' or 'test'. Depending on how
# you are testing.
RECOVERY_PHONE__TWILIO__CREDENTIAL_MODE=apiKeys
TIP:
- Applying .env file state is easy simply run
dotenv -- yarn start. - After toggling
RECOVERY_PHONE__TWILIO__CREDENTIAL_MODEyou can restart auth-server like this:dotenv -- yarn pm2 restart auth --update-env. This avoids having to stop and start the stack again.
We need to be able to periodically remove old tokens and codes. This can be accomplished via the token pruning script in the scripts directory.
For example to clear out tokens and codes older than 10 days execute the following:
./scripts/prune-tokens.sh —-maxTokenAge='10 days' --maxCodeAge='10 days'
For more info about the script usage execute the following:
./scripts/prune-tokens.sh --help
Note: In the wild, this script will be run periodically by our SRE team as part of database maintenance.
Firefox Accounts authorization is a complicated flow. You can get verbose logging by adjusting the log level in the config.json on your deployed instance. Add a stanza like:
"log": {
"level": "trace"
}
Valid level values (from least to most verbose logging) include: "fatal", "error", "warn", "info", "trace", "debug".
MPL 2.0