From 5eeac469dc9bf609f578bc306882d6cb22080f20 Mon Sep 17 00:00:00 2001 From: wxiaoguang Date: Tue, 26 Nov 2024 09:17:40 +0800 Subject: [PATCH] provide default auth flags --- models/auth/webauthn.go | 22 +++++++++++++++++++++- modules/auth/webauthn/webauthn.go | 8 +++++--- routers/web/auth/webauthn.go | 2 +- 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/models/auth/webauthn.go b/models/auth/webauthn.go index 553130ee2e9ee..6d8b54295790e 100644 --- a/models/auth/webauthn.go +++ b/models/auth/webauthn.go @@ -12,6 +12,7 @@ import ( "code.gitea.io/gitea/modules/timeutil" "code.gitea.io/gitea/modules/util" + "github.com/go-webauthn/webauthn/protocol" "github.com/go-webauthn/webauthn/webauthn" ) @@ -89,14 +90,33 @@ func (cred *WebAuthnCredential) AfterLoad() { // WebAuthnCredentialList is a list of *WebAuthnCredential type WebAuthnCredentialList []*WebAuthnCredential +// newCredentialFlagsFromAuthenticatorFlags is copied from https://github.com/go-webauthn/webauthn/pull/337 +// to convert protocol.AuthenticatorFlags to webauthn.CredentialFlags +func newCredentialFlagsFromAuthenticatorFlags(flags protocol.AuthenticatorFlags) webauthn.CredentialFlags { + return webauthn.CredentialFlags{ + UserPresent: flags.HasUserPresent(), + UserVerified: flags.HasUserVerified(), + BackupEligible: flags.HasBackupEligible(), + BackupState: flags.HasBackupState(), + } +} + // ToCredentials will convert all WebAuthnCredentials to webauthn.Credentials -func (list WebAuthnCredentialList) ToCredentials() []webauthn.Credential { +func (list WebAuthnCredentialList) ToCredentials(defaultAuthFlags ...protocol.AuthenticatorFlags) []webauthn.Credential { + // TODO: at the moment, Gitea doesn't store or check the flags + // so we need to use the default flags from the authenticator to make the login validation pass + // In the future, we should: + // 1. store the flags when registering the credential + // 2. provide the stored flags when converting the credentials (for login) + // 3. for old users, still use this fallback to the default flags + defAuthFlags := util.OptionalArg(defaultAuthFlags) creds := make([]webauthn.Credential, 0, len(list)) for _, cred := range list { creds = append(creds, webauthn.Credential{ ID: cred.CredentialID, PublicKey: cred.PublicKey, AttestationType: cred.AttestationType, + Flags: newCredentialFlagsFromAuthenticatorFlags(defAuthFlags), Authenticator: webauthn.Authenticator{ AAGUID: cred.AAGUID, SignCount: cred.SignCount, diff --git a/modules/auth/webauthn/webauthn.go b/modules/auth/webauthn/webauthn.go index e327de9d23c9d..cbf5279c651fd 100644 --- a/modules/auth/webauthn/webauthn.go +++ b/modules/auth/webauthn/webauthn.go @@ -43,12 +43,14 @@ func Init() { type user struct { ctx context.Context User *user_model.User + + defaultAuthFlags protocol.AuthenticatorFlags } var _ webauthn.User = (*user)(nil) -func NewWebAuthnUser(ctx context.Context, u *user_model.User) webauthn.User { - return &user{ctx: ctx, User: u} +func NewWebAuthnUser(ctx context.Context, u *user_model.User, defaultAuthFlags ...protocol.AuthenticatorFlags) webauthn.User { + return &user{ctx: ctx, User: u, defaultAuthFlags: util.OptionalArg(defaultAuthFlags)} } // WebAuthnID implements the webauthn.User interface @@ -74,5 +76,5 @@ func (u *user) WebAuthnCredentials() []webauthn.Credential { if err != nil { return nil } - return dbCreds.ToCredentials() + return dbCreds.ToCredentials(u.defaultAuthFlags) } diff --git a/routers/web/auth/webauthn.go b/routers/web/auth/webauthn.go index 4c106e261f43a..c00b4fcaf7f85 100644 --- a/routers/web/auth/webauthn.go +++ b/routers/web/auth/webauthn.go @@ -217,7 +217,7 @@ func WebAuthnLoginAssertionPost(ctx *context.Context) { } // Validate the parsed response. - webAuthnUser := wa.NewWebAuthnUser(ctx, user) + webAuthnUser := wa.NewWebAuthnUser(ctx, user, parsedResponse.Response.AuthenticatorData.Flags) cred, err := wa.WebAuthn.ValidateLogin(webAuthnUser, *sessionData, parsedResponse) if err != nil { // Failed authentication attempt.