Files
zitadel/backend/v3/domain/passkey.go
T
022bf74060 feat(session): Passkey Check API with relation tables (#11858)
# Which Problems Are Solved

As part of #11035 , this PR implements the Passkey check logic for
session validation

# How the Problems Are Solved

  - Refactor webauth FinishLogin to support new domain model
  - Add webauth config to defaults
  - Implement passkey check logic and tests
- Manual transaction management to avoid stalling the DB while
FinishLogin callback is executed
- Update passkey Type condition to allow passing a text operation
(equal, contains, etc..)

# Additional Context

This is a cherry-picked PR + minor changes, coming from
https://github.com/zitadel/zitadel/pull/11164
- Relates to #11035

---------

Co-authored-by: Fabienne Bühler <[email protected]>
Co-authored-by: Gayathri Vijayan <[email protected]>
2026-03-27 12:38:40 +01:00

82 lines
2.1 KiB
Go

package domain
import (
"context"
"github.com/go-webauthn/webauthn/protocol"
"github.com/go-webauthn/webauthn/webauthn"
"github.com/zitadel/zitadel/internal/api/http"
old_domain "github.com/zitadel/zitadel/internal/domain"
)
func PasskeysToCredentials(ctx context.Context, passkeys []*Passkey, rpID string) []webauthn.Credential {
creds := make([]webauthn.Credential, 0)
for _, pkey := range passkeys {
if !pkey.VerifiedAt.IsZero() &&
(pkey.RelyingPartyID == rpID ||
(pkey.RelyingPartyID == "" && rpID == http.DomainContext(ctx).InstanceDomain())) {
creds = append(creds, webauthn.Credential{
ID: pkey.KeyID,
PublicKey: pkey.PublicKey,
AttestationType: pkey.AttestationType,
Authenticator: webauthn.Authenticator{
AAGUID: pkey.AuthenticatorAttestationGUID,
SignCount: pkey.SignCount,
},
})
}
}
return creds
}
func UserVerificationFromDomain(verification old_domain.UserVerificationRequirement) protocol.UserVerificationRequirement {
switch verification {
case old_domain.UserVerificationRequirementRequired:
return protocol.VerificationRequired
case old_domain.UserVerificationRequirementPreferred:
return protocol.VerificationPreferred
case old_domain.UserVerificationRequirementDiscouraged, old_domain.UserVerificationRequirementUnspecified:
fallthrough
default:
return protocol.VerificationDiscouraged
}
}
type webAuthNUser struct {
userID string
username string
displayName string
creds []webauthn.Credential
}
// WebAuthnCredentials implements [webauthn.User].
func (w *webAuthNUser) WebAuthnCredentials() []webauthn.Credential {
return w.creds
}
// WebAuthnDisplayName implements [webauthn.User].
func (w *webAuthNUser) WebAuthnDisplayName() string {
return w.displayName
}
// WebAuthnID implements [webauthn.User].
func (w *webAuthNUser) WebAuthnID() []byte {
return []byte(w.userID)
}
// WebAuthnIcon implements [webauthn.User].
func (w *webAuthNUser) WebAuthnIcon() string {
return ""
}
// WebAuthnName implements [webauthn.User].
func (w *webAuthNUser) WebAuthnName() string {
return w.username
}
var _ webauthn.User = (*webAuthNUser)(nil)