mirror of
https://github.com/zitadel/zitadel.git
synced 2025-07-14 21:38:31 +00:00

# Which Problems Are Solved To prevent presenting unusable WebAuthN credentials to the user / browser, we filtered out all credentials, which do not match the requested RP ID. Since credentials set up through Login V1 and Console do not have an RP ID stored, they never matched. This was previously intended, since the Login V2 could be served on a separate domain. The problem is, that if it is hosted on the same domain, the credentials would also be filtered out and user would not be able to login. # How the Problems Are Solved Change the filtering to return credentials, if no RP ID is stored and the requested RP ID matches the instance domain. # Additional Changes None # Additional Context Noted internally when testing the login v2
92 lines
3.1 KiB
Go
92 lines
3.1 KiB
Go
package webauthn
|
|
|
|
import (
|
|
"context"
|
|
"strings"
|
|
|
|
"github.com/go-webauthn/webauthn/protocol"
|
|
"github.com/go-webauthn/webauthn/webauthn"
|
|
|
|
"github.com/zitadel/zitadel/internal/api/http"
|
|
"github.com/zitadel/zitadel/internal/domain"
|
|
)
|
|
|
|
func WebAuthNsToCredentials(ctx context.Context, webAuthNs []*domain.WebAuthNToken, rpID string) []webauthn.Credential {
|
|
creds := make([]webauthn.Credential, 0)
|
|
for _, webAuthN := range webAuthNs {
|
|
// only add credentials that are ready and
|
|
// either match the rpID or
|
|
// if they were added through Console / old login UI, there is no stored rpID set;
|
|
// then we check if the requested rpID matches the instance domain
|
|
if webAuthN.State == domain.MFAStateReady &&
|
|
(webAuthN.RPID == rpID ||
|
|
(webAuthN.RPID == "" && rpID == strings.Split(http.DomainContext(ctx).InstanceHost, ":")[0])) {
|
|
creds = append(creds, webauthn.Credential{
|
|
ID: webAuthN.KeyID,
|
|
PublicKey: webAuthN.PublicKey,
|
|
AttestationType: webAuthN.AttestationType,
|
|
Authenticator: webauthn.Authenticator{
|
|
AAGUID: webAuthN.AAGUID,
|
|
SignCount: webAuthN.SignCount,
|
|
},
|
|
})
|
|
}
|
|
}
|
|
return creds
|
|
}
|
|
|
|
func WebAuthNToSessionData(webAuthN *domain.WebAuthNToken) webauthn.SessionData {
|
|
return webauthn.SessionData{
|
|
Challenge: webAuthN.Challenge,
|
|
UserID: []byte(webAuthN.AggregateID),
|
|
AllowedCredentialIDs: webAuthN.AllowedCredentialIDs,
|
|
UserVerification: UserVerificationFromDomain(webAuthN.UserVerification),
|
|
}
|
|
}
|
|
|
|
func WebAuthNLoginToSessionData(webAuthN *domain.WebAuthNLogin) webauthn.SessionData {
|
|
return webauthn.SessionData{
|
|
Challenge: webAuthN.Challenge,
|
|
UserID: []byte(webAuthN.AggregateID),
|
|
AllowedCredentialIDs: webAuthN.AllowedCredentialIDs,
|
|
UserVerification: UserVerificationFromDomain(webAuthN.UserVerification),
|
|
}
|
|
}
|
|
|
|
func UserVerificationToDomain(verification protocol.UserVerificationRequirement) domain.UserVerificationRequirement {
|
|
switch verification {
|
|
case protocol.VerificationRequired:
|
|
return domain.UserVerificationRequirementRequired
|
|
case protocol.VerificationPreferred:
|
|
return domain.UserVerificationRequirementPreferred
|
|
case protocol.VerificationDiscouraged:
|
|
return domain.UserVerificationRequirementDiscouraged
|
|
default:
|
|
return domain.UserVerificationRequirementUnspecified
|
|
}
|
|
}
|
|
|
|
func UserVerificationFromDomain(verification domain.UserVerificationRequirement) protocol.UserVerificationRequirement {
|
|
switch verification {
|
|
case domain.UserVerificationRequirementRequired:
|
|
return protocol.VerificationRequired
|
|
case domain.UserVerificationRequirementPreferred:
|
|
return protocol.VerificationPreferred
|
|
case domain.UserVerificationRequirementDiscouraged:
|
|
return protocol.VerificationDiscouraged
|
|
default:
|
|
return protocol.VerificationDiscouraged
|
|
}
|
|
}
|
|
|
|
func AuthenticatorAttachmentFromDomain(authType domain.AuthenticatorAttachment) protocol.AuthenticatorAttachment {
|
|
switch authType {
|
|
case domain.AuthenticatorAttachmentPlattform:
|
|
return protocol.Platform
|
|
case domain.AuthenticatorAttachmentCrossPlattform:
|
|
return protocol.CrossPlatform
|
|
default:
|
|
return ""
|
|
}
|
|
}
|