Add webAuthn 2FA to support Yubikeys as additional 2nd factors#47
Merged
Conversation
Caveat from Claude: Since I removed all six callers, getNeosSettings() is now unused within BackendController — kept per your instruction, but a strict static-analysis run may flag it as unused. Mentioning so it's not a surprise.
716b155 to
099c431
Compare
…thn ceremony; Remove unused attestation setting; Fix redirect after WebAuthn login
…Authn are set up and restarting WebAuthn challenge
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.
Added WebAuthn / FIDO2 as a second option for Two Factor Authentication, so hardware security keys (e.g. Yubikeys) can be used as second factors alongside TOTP.
Breaking changes
php: ^8.2andneos/neos: ^8.0 | ^9.0.web-auth/webauthn-lib: ^4.9.3.spomky-labs/otphpto^11.5to ensure a security-fixed version.Migration (run after deployment)
Added migration
Version20260519120000.php:secretcolumn onsandstorm_neostwofactorauthentication_domain_model_secondfactorfromVARCHAR(255)toTEXT, so it can hold the serialized WebAuthn credential data (which exceeds 255 chars). Without it, registering a security key will fail to persist../flow doctrine:migrateConfiguration
Added settings for WebAuthn configuration (relying party, user verification, timeout) — see
Settings.yamland the README for examples and authenticator compatibility notes.Note: browsers expose WebAuthn only over
https://or onlocalhost, so the backend must be served over HTTPS in production for the security-key flow to work.Attestation
By design, we do not implement attestation statement formats other than
none. We always request thenoneconveyance preference, so the browser does not return identifying attestation data about the authenticator. When loading a credential, only thenoneandfido-u2fattestation statement formats are accepted (fido-u2fis required for U2F-only authenticators registered via the browser's U2F-compat fallback). Other attestation statement types are not supported. This keeps the implementation simpler and avoids collecting authenticator-identifying data we don't need for second-factor verification.Tests
Added E2E tests (login and backend module) covering WebAuthn registration and login, including the case where both OTP and WebAuthn are set up and the WebAuthn challenge is restarted.
Screenshots
Register 2nd Factor Select Screen:

Register Security Key Screen:

List of registered 2nd Factors Screen:

Second factor login Screen:
