Add WebAuthn credential registration#128
Conversation
|
The security team is monitoring all repositories for certain keywords. This PR includes the word(s) "authn" and so security team members have been added as reviewers to take a look. |
|
[puLL-Merge] - brave/accounts@128 DescriptionThis PR adds WebAuthn (Web Authentication) support to the Brave accounts service, enabling users to configure hardware security keys and biometric authentication as a second factor alongside TOTP. The implementation uses the go-webauthn library and includes credential management (registration, storage, and deletion), integration with the existing 2FA flow, and proper database migrations. Key changes:
Security Hotspots
Privacy Hotspots
ChangesChanges
Test files
sequenceDiagram
participant Client
participant AccountsController
participant TwoFAService
participant Datastore
participant WebAuthn
%% Registration Flow
Client->>AccountsController: POST /2fa/webauthn/init
AccountsController->>TwoFAService: CreateWebAuthnRegistrationChallenge
TwoFAService->>Datastore: GetOrCreateWebAuthnID
Datastore-->>TwoFAService: webauthnID
TwoFAService->>Datastore: GetWebAuthnCredentials
Datastore-->>TwoFAService: existing credentials
TwoFAService->>WebAuthn: BeginMediatedRegistration
WebAuthn-->>TwoFAService: CredentialCreation + SessionData
TwoFAService->>Datastore: CreateInterimWebAuthnState
Datastore-->>TwoFAService: registrationID
TwoFAService-->>AccountsController: CredentialCreation + registrationID
AccountsController-->>Client: Challenge + registrationID
Client->>Client: User interacts with authenticator
Client->>AccountsController: POST /2fa/webauthn/finalize<br/>(registrationID, name, response)
AccountsController->>TwoFAService: FinalizeWebAuthnCredentialRegistration
TwoFAService->>Datastore: GetAndDeleteInterimWebAuthnState
Datastore-->>TwoFAService: SessionData
TwoFAService->>Datastore: GetWebAuthnCredentials (for user object)
Datastore-->>TwoFAService: credentials
TwoFAService->>WebAuthn: CreateCredential
WebAuthn-->>TwoFAService: Credential (validated)
TwoFAService->>Datastore: SaveWebAuthnCredential
Datastore-->>TwoFAService: success
TwoFAService-->>AccountsController: credential
AccountsController->>AccountsController: maybeGenerateRecoveryKey
AccountsController->>Datastore: SetWebAuthnSetting(true)
Datastore-->>AccountsController: success
AccountsController-->>Client: TwoFAFinalizeResponse (with recovery key if new)
%% Credential Deletion Flow
Client->>AccountsController: DELETE /2fa/webauthn/{credentialID}
AccountsController->>Datastore: GetWebAuthnCredentials
Datastore-->>AccountsController: all credentials
alt Last credential
AccountsController->>Datastore: SetWebAuthnSetting(false)
end
AccountsController->>Datastore: DeleteWebAuthnCredential
Datastore-->>AccountsController: success
AccountsController-->>Client: 204 No Content
|
| return | ||
| } | ||
|
|
||
| // Get all credentials to check if this is the last one |
There was a problem hiding this comment.
Maybe we should put this in a transaction to eliminate any possible races?
#102