feat(profile-sync): add MFA validation foundation - #10264
Merged
Merged
Conversation
mathieuartu
added this pull request to stack #10268
September 16, 2026 13:42
4 tasks
mathieuartu
force-pushed
the
mfa/sdk-foundation
branch
2 times, most recently
from
September 16, 2026 20:13
ebd08b3 to
72c255a
Compare
gantunesr
reviewed
Sep 16, 2026
gantunesr
reviewed
Sep 17, 2026
Co-authored-by: Cursor <cursoragent@cursor.com>
- Read aal/amr from top-level or Hydra ext claims - Derive credential type from proof; add reason to completion requests - Split mfa_identity_missing from flow-expired errors; add rate_limited - Accept unknown credential statuses; drop unused description/BAD_REQUEST - MfaUnavailableError no longer invents a 502 for transport failures Co-authored-by: Cursor <cursoragent@cursor.com>
mathieuartu
force-pushed
the
mfa/sdk-foundation
branch
from
September 17, 2026 06:48
72c255a to
8305b87
Compare
mathieuartu
force-pushed
the
mfa/sdk-foundation
branch
from
September 17, 2026 06:54
a59b527 to
d6d147b
Compare
gantunesr
approved these changes
Sep 17, 2026
pull Bot
pushed a commit
to Reality2byte/core
that referenced
this pull request
Sep 18, 2026
## Explanation Wires the MFA HTTP client into the SRP JWT auth SDK on top of the validation foundation. - `mfa/services` calls `/api/v2/mfa/*` (enroll, enroll complete, verify, verify complete, credentials), validates request/response bodies, maps server codes to `MfaError` subclasses, and handles OTP cooldown / `Retry-After`. - `SRPJwtBearerAuth` exposes begin/complete enrollment and verification, credential listing, and assertion-to-token exchange. - Public `JwtBearerAuth` forwards those methods and rejects non-SRP auth types. - Nock fixtures and unit tests cover happy paths and error mapping. Clients still go through `AuthenticationController` in later PRs; this layer is not UI-facing. ## References Depends on MetaMask#10264. Follow-ups: MetaMask#10266, MetaMask#10267. Stack: [stack #10268](https://github.com/MetaMask/core/pull/10268). Related to: https://consensyssoftware.atlassian.net/browse/MUL-2261 ## Checklist - [x] I've updated the test suite for new or updated code as appropriate - [x] I've updated documentation (JSDoc, Markdown, etc.) for new or updated code as appropriate - [x] I've communicated my changes to consumers by [updating changelogs for packages I've changed](https://github.com/MetaMask/core/tree/main/docs/processes/updating-changelogs.md) - [ ] I've introduced [breaking changes](https://github.com/MetaMask/core/tree/main/docs/processes/breaking-changes.md) in this PR and have prepared draft pull requests for clients and consumer packages to resolve them <!-- CURSOR_SUMMARY --> --- > [!NOTE] > **High Risk** > Touches authentication, step-up tokens, and passkey/OTP handling; mistakes could weaken session elevation or mishandle credentials, though coverage is extensive. > > **Overview** > Adds **passkey and email OTP MFA** to the profile-sync JWT auth SDK: a new HTTP layer calls `/api/v2/mfa/*` (enroll, complete, verify, credentials), validates payloads, maps server codes to `MfaError` subclasses, and handles OTP cooldown plus `Retry-After`. > > **`SRPJwtBearerAuth`** and public **`JwtBearerAuth`** expose enrollment/step-up flows, credential listing, and **`exchangeMfaAssertion`** (AAL2 JWT → elevated access token via existing OIDC). MFA is **SRP-only**; email enrollment uses a separate `email` option from `entropySourceId`. > > Schemas mark challenges, OTP codes, passkey payloads, and tokens with **`sensitive()`**. Tests, nock fixtures, changelog, and SDK exports for MFA types are included. > > <sup>Reviewed by [Cursor Bugbot](https://cursor.com/bugbot) for commit 56b3671. Bugbot is set up for automated code reviews on this repo. Configure [here](https://www.cursor.com/dashboard/bugbot).</sup> <!-- /CURSOR_SUMMARY --> --------- Co-authored-by: Cursor <cursoragent@cursor.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Explanation
Adds the MFA validation layer in
@metamask/profile-sync-controllerthat later PRs in this stack consume.MfaErrorfamily with a stable enumerablemfaCode, plus helpers that survive JSON-RPC serialization (getMfaErrorCode,isMfaError,getMfaRetryAfterMs).decodeJwtPayload(no signature verification) and slightly stricter login JWTexphandling.HTTP_STATUS_CODESfor later MFA error mapping.This PR does not call MFA HTTP endpoints or change controller behavior.
References
Stacked under stack #10268. Follow-ups: #10265, #10266, #10267.
Related to: https://consensyssoftware.atlassian.net/browse/MUL-2260
Checklist
Note
Medium Risk
Touches authentication-adjacent validation, JWT claim handling, and structured MFA errors, though runtime sign-in/MFA flows are unchanged until follow-up PRs.
Overview
Introduces the MFA validation layer in
@metamask/profile-sync-controllerfor later stack PRs—no MFA HTTP calls or controller behavior changes in this diff.Adds Superstruct schemas and inferred types under
authentication-jwt-bearer/mfafor passkey and email OTP flows: auth-service responses, WebAuthn ceremony payloads, enrollment/step-up requests, and AAL2 elevated-token claim parsing (including Hydraextnesting).assertValidMfaRequest/assertValidMfaResponsemap validation failures toMfaErrorwith path details.Expands
MfaErrorwith typed subclasses, stable enumerablemfaCode, and helpers (getMfaErrorCode,isMfaError,getMfaRetryAfterMs) that work after JSON-RPC serialization. Adds shareddecodeJwtPayloadand refactors login JWT expiry checks to use it with stricterexptyping.HTTP_STATUS_CODESgains401and502for upcoming error mapping.Dependencies:
@metamask/superstruct(runtime),@metamask/rpc-errors(tests). Changelog updated.Reviewed by Cursor Bugbot for commit d6d147b. Bugbot is set up for automated code reviews on this repo. Configure here.