[FEAT] Add support for webauthn credential level 3

- For WebAuthn Credential level 3, the `backup_eligible` and
`backup_state` flags are checked if they are consistent with the values
given on login. Forgejo never stored this data, so add a database
migration that makes all webauthn credentials 'legacy' and on the next
first use capture the values of `backup_eligible` and `backup_state`.
As suggested in https://github.com/go-webauthn/webauthn/discussions/219#discussioncomment-10429662
- Adds unit tests.
- Add E2E test.
This commit is contained in:
Gusted 2024-08-28 07:40:40 +02:00
parent 28c3f1e254
commit 63736e8301
No known key found for this signature in database
GPG key ID: FD821B732837125F
7 changed files with 131 additions and 12 deletions

View file

@ -116,6 +116,25 @@ func WebAuthnLoginAssertionPost(ctx *context.Context) {
return
}
dbCred, err := auth.GetWebAuthnCredentialByCredID(ctx, user.ID, parsedResponse.RawID)
if err != nil {
ctx.ServerError("GetWebAuthnCredentialByCredID", err)
return
}
// If the credential is legacy, assume the values are correct. The
// specification mandates these flags don't change.
if dbCred.Legacy {
dbCred.BackupEligible = parsedResponse.Response.AuthenticatorData.Flags.HasBackupEligible()
dbCred.BackupState = parsedResponse.Response.AuthenticatorData.Flags.HasBackupState()
dbCred.Legacy = false
if err := dbCred.UpdateFromLegacy(ctx); err != nil {
ctx.ServerError("UpdateFromLegacy", err)
return
}
}
// Validate the parsed response.
cred, err := wa.WebAuthn.ValidateLogin((*wa.User)(user), *sessionData, parsedResponse)
if err != nil {
@ -133,13 +152,6 @@ func WebAuthnLoginAssertionPost(ctx *context.Context) {
return
}
// Success! Get the credential and update the sign count with the new value we received.
dbCred, err := auth.GetWebAuthnCredentialByCredID(ctx, user.ID, cred.ID)
if err != nil {
ctx.ServerError("GetWebAuthnCredentialByCredID", err)
return
}
dbCred.SignCount = cred.Authenticator.SignCount
if err := dbCred.UpdateSignCount(ctx); err != nil {
ctx.ServerError("UpdateSignCount", err)