package auth import ( "encoding/json" "git.mstar.dev/mstar/goutils/sliceutils" "github.com/go-webauthn/webauthn/webauthn" "github.com/rs/zerolog/log" "git.mstar.dev/mstar/linstrom/storage-new/models" ) // A fake user struct for implementing the webauthn.User interface // on top of the storage system type fakeUser struct { actualUser *models.User } // Ensure that fakeUser always implements webauthn.User var _ webauthn.User = &fakeUser{} // WebAuthnID provides the user handle of the user account. A user handle is an opaque byte sequence with a maximum // size of 64 bytes, and is not meant to be displayed to the user. // // To ensure secure operation, authentication and authorization decisions MUST be made on the basis of this id // member, not the displayName nor name members. See Section 6.1 of [RFC8266]. // // It's recommended this value is completely random and uses the entire 64 bytes. // // Specification: §5.4.3. User Account Parameters for Credential Generation (https://w3c.github.io/webauthn/#dom-publickeycredentialuserentity-id) func (fakeuser *fakeUser) WebAuthnID() []byte { return fakeuser.actualUser.PasskeyId } // WebAuthnName provides the name attribute of the user account during registration and is a human-palatable name for the user // account, intended only for display. For example, "Alex Müller" or "田中倫". The Relying Party SHOULD let the user // choose this, and SHOULD NOT restrict the choice more than necessary. // // Specification: §5.4.3. User Account Parameters for Credential Generation (https://w3c.github.io/webauthn/#dictdef-publickeycredentialuserentity) func (fakeuser *fakeUser) WebAuthnName() string { return fakeuser.actualUser.DisplayName } // WebAuthnDisplayName provides the name attribute of the user account during registration and is a human-palatable // name for the user account, intended only for display. For example, "Alex Müller" or "田中倫". The Relying Party // SHOULD let the user choose this, and SHOULD NOT restrict the choice more than necessary. // // Specification: §5.4.3. User Account Parameters for Credential Generation (https://www.w3.org/TR/webauthn/#dom-publickeycredentialuserentity-displayname) func (fakeuser *fakeUser) WebAuthnDisplayName() string { return fakeuser.actualUser.DisplayName } // WebAuthnCredentials provides the list of Credential objects owned by the user. func (fakeuser *fakeUser) WebAuthnCredentials() []webauthn.Credential { // Basically just convert the relevant entries from the user to a credential return sliceutils.Map(sliceutils.Filter( fakeuser.actualUser.AuthMethods, func(t models.UserAuthMethod) bool { return t.AuthMethod == models.AuthMethodPasskey || t.AuthMethod == models.AuthMethodPasskey2fa }), func(t models.UserAuthMethod) webauthn.Credential { var c webauthn.Credential if err := json.Unmarshal(t.Token, &c); err != nil { // TODO: Is there any better way to handle the error here? log.Error().Err(err).Msg("Failed to unmarshal webauthn credential") } return c }) }