feat(auth): add WebAuthn MFA credentials (#1628)

* feat(auth): add WebAuthn MFA credentials

* fix(auth): harden WebAuthn MFA review paths

* fix(auth): polish WebAuthn error handling

* fix(auth): handle duplicate WebAuthn credential races

* fix(auth): permit WebAuthn credential params

* fix(auth): trim WebAuthn registration controller cleanup

* fix(auth): tighten WebAuthn MFA handling

* fix(auth): pin WebAuthn relying party config
This commit is contained in:
ghost
2026-05-03 14:13:28 -06:00
committed by GitHub
parent faf31b9c91
commit 911aa34ba9
29 changed files with 1117 additions and 10 deletions

View File

@@ -102,11 +102,45 @@ class UserTest < ActiveSupport::TestCase
user = users(:family_member)
user.setup_mfa!
user.enable_mfa!
user.webauthn_credentials.create!(
nickname: "YubiKey",
credential_id: "credential-id",
public_key: "public-key"
)
user.disable_mfa!
assert_nil user.otp_secret
assert_not user.otp_required?
assert_empty user.otp_backup_codes
assert_empty user.webauthn_credentials
end
test "ensure_webauthn_id! generates a stable credential user handle" do
user = users(:family_member)
assert_nil user.webauthn_id
webauthn_id = user.ensure_webauthn_id!
assert webauthn_id.present?
assert_equal webauthn_id, user.reload.ensure_webauthn_id!
end
test "webauthn_enabled? requires MFA and at least one credential" do
user = users(:family_member)
assert_not user.webauthn_enabled?
user.setup_mfa!
user.enable_mfa!
assert_not user.webauthn_enabled?
user.webauthn_credentials.create!(
nickname: "Touch ID",
credential_id: "touch-id-credential",
public_key: "public-key"
)
assert user.webauthn_enabled?
end
test "verify_otp? validates TOTP codes" do