fix(passkeys): always require user verification in WebAuthn ceremonies#20725
Open
vpomerleau wants to merge 1 commit into
Open
fix(passkeys): always require user verification in WebAuthn ceremonies#20725vpomerleau wants to merge 1 commit into
vpomerleau wants to merge 1 commit into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR strengthens passkey/WebAuthn security by making user verification (UV) a non-configurable invariant and enforcing it server-side during both registration and authentication ceremonies, preventing issuance of an AAL2 session when the authenticator did not perform UV.
Changes:
- Hardcode
userVerification: 'required'when generating WebAuthn options and enforcerequireUserVerification: truewhen verifying responses. - Remove the
userVerificationconfiguration knob (including the convict env var) so it cannot be relaxed. - Update route schemas and extend the VirtualAuthenticator/tests to cover UV-unset negative cases.
Reviewed changes
Copilot reviewed 9 out of 9 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/fxa-auth-server/lib/routes/passkeys.ts | Narrows response schema values for userVerification to 'required'. |
| packages/fxa-auth-server/config/index.ts | Removes PASSKEYS__USER_VERIFICATION convict config entry. |
| libs/accounts/passkey/src/lib/webauthn-adapter.ts | Forces UV-required option generation and enforces UV during verification. |
| libs/accounts/passkey/src/lib/webauthn-adapter.spec.ts | Adds regression tests ensuring UV-unset responses are rejected; updates existing expectations. |
| libs/accounts/passkey/src/lib/virtual-authenticator.ts | Adds a test hook to clear the UV flag in authenticator-data for negative testing. |
| libs/accounts/passkey/src/lib/passkey.service.spec.ts | Removes userVerification from PasskeyConfig test setup. |
| libs/accounts/passkey/src/lib/passkey.provider.ts | Removes userVerification from raw config type/imports. |
| libs/accounts/passkey/src/lib/passkey.provider.spec.ts | Updates raw config fixture expectations to match knob removal. |
| libs/accounts/passkey/src/lib/passkey.config.ts | Removes userVerification from PasskeyConfig and its validation/docs. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
5d9f6d8 to
e49b0aa
Compare
Because: - Passkey sign-in mints an AAL2 session token and bypasses TOTP, so user verification must always occur. The simplewebauthn verify calls omitted requireUserVerification (defaults to false), so a UV-unset response was accepted; UV was also a config knob that could be relaxed to 'preferred'. This commit: - Hardcodes requireUserVerification: true on both the registration and authentication verify calls, and userVerification: 'required' on both option-generation calls. - Removes the userVerification config knob (PasskeyConfig, RawPasskeyConfig, and convict PASSKEYS__USER_VERIFICATION) so UV can no longer be relaxed. - Adds an optional userVerified flag to the test VirtualAuthenticator and regression tests asserting a UV-unset response is rejected. Closes: FXA-13941
e49b0aa to
8eb5055
Compare
vbudhram
approved these changes
Jun 11, 2026
| .string() | ||
| .valid('discouraged', 'preferred', 'required') | ||
| .optional(), | ||
| userVerification: isA.string().valid('required').required(), |
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.
Because
verification must always occur. The server's
@simplewebauthn/serververifycalls omitted
requireUserVerification(which defaults tofalse), so aWebAuthn response with the user-verified flag cleared was accepted — granting
an AAL2 session to a present-but-unverified user.
'preferred'/'discouraged', weakening the guarantee. This must be fixedbefore the Phase 1 production rollout.
This pull request
requireUserVerification: trueon bothverifyWebauthnRegistrationResponseandverifyWebauthnAuthenticationResponse,and
userVerification: 'required'on both option-generation functions inlibs/accounts/passkey/src/lib/webauthn-adapter.ts.userVerificationconfig knob entirely — fromPasskeyConfig,RawPasskeyConfig, and the convictPASSKEYS__USER_VERIFICATIONsetting inpackages/fxa-auth-server/config/index.ts— so user verification can nolonger be relaxed.
packages/fxa-auth-server/lib/routes/passkeys.tstovalid('required'),dropping the now-unreachable
'preferred'/'discouraged'values.userVerifiedflag to the testVirtualAuthenticatorandregression tests asserting a UV-unset response is rejected for both ceremonies.
Issue that this pull request solves
Closes: FXA-13941
Checklist
Put an
xin the boxes that applyHow to review (Optional)
webauthn-adapter.ts(the enforcement — bothrequireUserVerification: trueand the'required'options); the knob removal acrosspasskey.config.ts,passkey.provider.ts, andconfig/index.ts.virtual-authenticator.tsUV-flag bit math → the new negative tests.virtual-authenticator.ts(UV bit clearing) underpins the regression tests.Screenshots (Optional)
Please attach the screenshots of the changes made in case of change in user interface.
Other information (Optional)
PASSKEYS__USER_VERIFICATIONenv var if it is set in any stage/prod config. With the convict key removed it is now inert (convict ignores an env var with no matching schema key, so there is no runtime break), but it should be cleaned up so it doesn't linger as a dead variable.