Because:
ADR-0022 (2020) sanctioned dropping Hawk for in-monorepo callers. FXA-9392
attempted this in 2024 but was reverted because plain "Bearer <hex>"
collided with the refresh-token strategy. This change uses prefixed Bearer
tokens (GitHub/Stripe pattern) so the wire format is disjoint from the
refresh-token scheme.
This commit:
* Adds a server-side bearer-fxa-token Hapi auth scheme. Wire format:
"Authorization: Bearer <prefix>_<hex>" where the prefix encodes the
token kind (fxs_, fxk_, fxar_, fxpf_, fxpc_). keyFetchToken and
keyFetchTokenWithVerificationStatus deliberately share the fxk_ prefix
on the wire (the client only ever derives one keyFetch credential; the
with-verification variant differs only in the server-side DB lookup).
Strategies registered for all six token kinds plus non-throwing
multi-strategy variants and a verifiedSessionTokenBearer that shares
the post-lookup guard with the existing Hawk-backed verifiedSessionToken
(extracted to makePostLookupGuard).
* Flips every protected route (including the deprecated /account/sessions
endpoint, kept compatible for any client that adopts the Bearer auth-
client) to a multi-strategy chain with Bearer first and Hawk as
fallback, around 65 auth configs across 17 files:
single-strategy session/keyFetch/accountReset/passwordForgot/
passwordChange/verifiedSession routes, the four-way
multiStrategySessionToken chains, and the [sessionToken, refreshToken]
and [sessionToken, oauthToken] chains. Handler-side auth.strategy
checks broadened to accept the new Bearer variants.
* Fixes the Hawk scheme's missing-header branch to respect
throwOnFailure: false so multi-strategy chains can fall through
cleanly. Adds auth.strategy.used{scheme,kind} StatsD counter to both
schemes for observability of the migration.
* Strategy options are runtime-required: bearer and hawk strategy()
factories now validate that throwOnFailure, statsd, and (hawk) kind
are passed explicitly. server.js call sites updated to pass
throwOnFailure on every registration. Eliminates the prior class of
bug where a registration silently disappeared from the
auth.strategy.used dashboard because statsd/kind were omitted.
* All fallthrough error paths in both strategies return an AppError
with errno=110, "Token not found", isBoom=true instead of
Boom.unauthorized(null, scheme). A final 401 from a multi-strategy
chain is wire-compatible with the typed single-strategy "Token not
found" response. Regression tests assert errno=110 in the
throwOnFailure=false branches.
* Migrates fxa-auth-client: new lib/bearer.ts::bearerHeader, renames
hawkRequest to authedRequest, deletes Hawk signing code from
lib/hawk.ts, switches the three deriveHawkCredentials call sites to
deriveTokenCredentials. Adds test/no-hawk-signing.ts regression
guard. Updates fxa-settings/src/lib/auth-key-stretch-upgrade.ts to
the new alias.
* Hardens fxa-auth-server/lib/sentry.js filterExtras with a single
key-fragment redact list (auth, cookie, pw, kb, key) plus an
unanchored value-pattern redactor for prefixed Bearer tokens so
the raw id cannot leak into Sentry extras even when embedded in a
larger string (stack frame, URL, error message).
* Updates ADR-0022 status to "Partially Implemented" with notes on
what is intentionally out of scope (server-side Hawk stays for
external clients: Firefox Desktop, iOS, Android, Sync).
* Adds ADR-0050 documenting the prefixed-Bearer token naming
convention, the rejected alternatives (plain Bearer, custom
Authorization scheme, JWT), and the rules for allocating new
prefixes.
Tests: auth-server Jest 3414/3414, auth-client Mocha 26/26,
fxa-settings auth-adjacent tests 274/274; tsc clean on auth-server,
auth-client, fxa-settings, fxa-admin-server. Remote test exercising
the Bearer path end-to-end added for /totp/verify; existing remote
suite continues to exercise Hawk fallback because test/client/api.js
sends Hawk headers.
Fixes FXA-9392