package webauthnutil import ( "github.com/google/uuid" "github.com/pomerium/pomerium/pkg/grpc/user" "github.com/pomerium/webauthn" ) var pomeriumUserNamespace = uuid.MustParse("2929d3f7-f0b0-478f-9dd5-970d51eb3859") // GetUserEntity gets the PublicKeyCredentialUserEntity from a Pomerium user. func GetUserEntity(pomeriumUser *user.User) webauthn.PublicKeyCredentialUserEntity { name := pomeriumUser.GetEmail() if name == "" { name = pomeriumUser.GetId() } displayName := pomeriumUser.GetName() if displayName == "" { displayName = name } return webauthn.PublicKeyCredentialUserEntity{ ID: GetUserEntityID(pomeriumUser.GetId()), DisplayName: displayName, Name: name, } } // GetUserEntityID gets the UserEntity ID. // // The WebAuthn spec states: // // > The user handle of the user account entity. 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]. // > // > The user handle MUST NOT contain personally identifying information about the user, such as a username or e-mail // > address; see ยง14.6.1 User Handle Contents for details. The user handle MUST NOT be empty, though it MAY be // > null. // // To meet these requirements we hash the user ID (since it's often an email address in the IdP) using a UUID v5 in a // custom UUID namespace: 2929d3f7-f0b0-478f-9dd5-970d51eb3859. func GetUserEntityID(pomeriumUserID string) []byte { id := uuid.NewSHA1(pomeriumUserNamespace, []byte(pomeriumUserID)) return id[:] }