Documentation
¶
Overview ¶
Package passkey implements WebAuthn / FIDO2 biometric and security key registration and passwordless authentication.
Index ¶
- Constants
- Variables
- func RegisterSchema(s *schema.Schema) error
- type AuthenticationOptions
- type BeginAuthenticationInput
- type BeginRegistrationInput
- type Capability
- type CeremonyError
- type Config
- type DeleteCredentialInput
- type FinishAuthenticationInput
- type FinishRegistrationInput
- type Hooks
- type Module
- type Option
- func WithChallengeStore(cs challenge.Store) Option
- func WithDebug(debug bool) Option
- func WithEnforceSignCounter(enforce bool) Option
- func WithHooks(h *Hooks) Option
- func WithRP(id, displayName string, origins []string) Option
- func WithResidentKey(rk protocol.ResidentKeyRequirement) Option
- func WithTimeout(d time.Duration) Option
- func WithUserVerification(uv protocol.UserVerificationRequirement) Option
- type Passkey
- type PasskeyRegisteredPayload
- type PasskeyRevokedPayload
- type PasskeyUsedPayload
- type Passkeys
- type RegistrationOptions
- type UpdateCredentialInput
Constants ¶
const ( // EventPasskeyRegistered is emitted when a new passkey credential is successfully registered. EventPasskeyRegistered auth.EventName = "passkey.registered" // EventPasskeyUsed is emitted when a user successfully authenticates using a passkey. EventPasskeyUsed auth.EventName = "passkey.used" // EventPasskeyRevoked is emitted when a passkey credential is deleted or revoked. EventPasskeyRevoked auth.EventName = "passkey.revoked" )
const DefaultTimeout = 60 * time.Second
DefaultTimeout is the default duration for WebAuthn ceremony expiration.
const (
ModelPasskeys = "passkeys"
)
const PluginID = "passkey"
PluginID is the unique identifier for this plugin module in GoModularAuth.
const ProviderPasskey = "passkey"
ProviderPasskey is the provider identifier used when recording linked passkey accounts in Core.
Variables ¶
var ( // ErrRPIDRequired indicates that relying party ID was not provided. ErrRPIDRequired = errors.New("passkey: relying party ID is required") // ErrRPDisplayNameRequired indicates that relying party display name was not provided. ErrRPDisplayNameRequired = errors.New("passkey: relying party display name is required") // ErrRPOriginsRequired indicates that at least one relying party origin is required. ErrRPOriginsRequired = errors.New("passkey: at least one relying party origin is required") // ErrInvalidRPID indicates that relying party ID contains an invalid scheme, port, or path. ErrInvalidRPID = errors.New("passkey: relying party ID must not contain schemes, ports, or paths") // ErrInvalidRPOrigin indicates that an origin URL is invalid or malformed. ErrInvalidRPOrigin = errors.New("passkey: relying party origin must be a valid URL with scheme") // ErrUserIDRequired indicates that a user ID was not supplied when required. ErrUserIDRequired = errors.New("passkey: user ID is required") // ErrCredentialIDRequired indicates that a credential ID was not provided. ErrCredentialIDRequired = errors.New("passkey: credential ID is required") // ErrSessionIDRequired indicates that a ceremony session ID was not provided. ErrSessionIDRequired = errors.New("passkey: ceremony session ID is required") // ErrChallengeNotFound indicates that the ceremony challenge does not exist. ErrChallengeNotFound = errors.New("passkey: ceremony challenge not found") // ErrChallengeExpired indicates that the ceremony challenge has expired. ErrChallengeExpired = errors.New("passkey: ceremony challenge has expired") // ErrChallengeAlreadyUsed indicates that the ceremony challenge was already consumed (replay prevention). ErrChallengeAlreadyUsed = errors.New("passkey: ceremony challenge has already been consumed") // ErrChallengeTypeMismatch indicates that the ceremony challenge type does not match the attempted operation. ErrChallengeTypeMismatch = errors.New("passkey: ceremony challenge type mismatch") // ErrInvalidClientResponse indicates that the browser client response was missing or malformed. ErrInvalidClientResponse = errors.New("passkey: invalid webauthn client response data") // ErrRegistrationFailed indicates that WebAuthn registration verification failed. ErrRegistrationFailed = errors.New("passkey: credential registration verification failed") // ErrAuthenticationFailed indicates that WebAuthn authentication verification failed. ErrAuthenticationFailed = errors.New("passkey: credential authentication verification failed") // ErrCredentialNotFound indicates that the requested passkey credential does not exist. ErrCredentialNotFound = errors.New("passkey: credential not found") // ErrCredentialAlreadyExists indicates that the credential ID is already registered. ErrCredentialAlreadyExists = errors.New("passkey: credential already registered") // ErrSignCounterInvalid indicates that the authenticator sign counter did not increment properly. ErrSignCounterInvalid = errors.New("passkey: sign counter invalid, potential replay or cloned authenticator") // ErrAuthenticatorCloned indicates that an authenticator clone was flagged during assertion verification. ErrAuthenticatorCloned = errors.New("passkey: authenticator clone detected") // ErrUserNotFound indicates that the user associated with the credential was not found in the core store. ErrUserNotFound = errors.New("passkey: user not found") ErrUnauthorized = errors.New("passkey: unauthorized access to credential") )
Functions ¶
func RegisterSchema ¶
RegisterSchema registers the passkeys model into the compiled schema.
Types ¶
type AuthenticationOptions ¶
type AuthenticationOptions struct {
// SessionID is the opaque challenge session identifier used to finish authentication.
SessionID string `json:"session_id"`
// Options contains the standard WebAuthn PublicKeyCredentialRequestOptions.
Options *protocol.CredentialAssertion `json:"options"`
// ExpiresAt specifies when the challenge expires.
ExpiresAt time.Time `json:"expires_at"`
}
AuthenticationOptions represents the authentication challenge options for the client.
type BeginAuthenticationInput ¶
type BeginAuthenticationInput struct {
// UserID is optional. If provided, server restricts allowed credentials to this user.
// If empty, discoverable (usernameless / resident key) authentication is initiated.
UserID string
// UserVerification overrides the default user verification requirement.
UserVerification protocol.UserVerificationRequirement
}
BeginAuthenticationInput contains options for starting an authentication ceremony.
type BeginRegistrationInput ¶
type BeginRegistrationInput struct {
// UserID identifies the user registering a passkey. Required.
UserID string
// FriendlyName is an optional human label for the device (e.g. "Pixel 8 Pro").
FriendlyName string
// UserVerification overrides the default user verification requirement.
UserVerification protocol.UserVerificationRequirement
// ResidentKey overrides the default resident key requirement.
ResidentKey protocol.ResidentKeyRequirement
// AuthenticatorAttachment optionally restricts attachment (platform or cross-platform).
AuthenticatorAttachment protocol.AuthenticatorAttachment
}
BeginRegistrationInput contains options for starting a credential registration ceremony.
type Capability ¶
type Capability = Passkeys
Capability is an alias for Passkeys for idiomatic capability retrieval.
type CeremonyError ¶
CeremonyError provides rich contextual error details around WebAuthn failures.
func (*CeremonyError) Error ¶
func (e *CeremonyError) Error() string
Error returns the string representation of CeremonyError.
func (*CeremonyError) Unwrap ¶
func (e *CeremonyError) Unwrap() error
Unwrap returns the underlying error.
type Config ¶
type Config struct {
// RPDisplayName is the human-readable Relying Party name (e.g. "Acme Corp"). Required.
RPDisplayName string
// RPID is the Relying Party server identifier (e.g. "acme.com" or "localhost"). Required.
RPID string
// RPOrigins lists the allowed origin URLs (e.g. "https://acme.com", "http://localhost:3000"). Required.
RPOrigins []string
// UserVerification specifies the default user verification requirement (required, preferred, discouraged).
// Default: preferred.
UserVerification protocol.UserVerificationRequirement
// ResidentKey specifies the default resident key / discoverable credential requirement.
// Default: preferred.
ResidentKey protocol.ResidentKeyRequirement
// Timeout defines the maximum duration allowed to complete a registration or login ceremony.
// Default: 60 seconds.
Timeout time.Duration
// EnforceSignCounter ensures that authenticator sign counter regressions trigger clone detection errors.
// Default: true.
EnforceSignCounter bool
// ChallengeStore is the storage adapter for transient ceremony challenges.
// Defaults to in-memory challenge store if nil.
ChallengeStore challenge.Store
// Hooks provides extension hooks for ceremony workflows.
Hooks *Hooks
// Debug enables verbose debug logging in the WebAuthn engine.
Debug bool
}
Config holds the configuration settings for the Passkey plugin.
type DeleteCredentialInput ¶
type DeleteCredentialInput struct {
// UserID verifies ownership. Required.
UserID string
// CredentialID is the binary ID of the credential to delete. Required.
CredentialID []byte
}
DeleteCredentialInput holds parameters for deleting a passkey.
type FinishAuthenticationInput ¶
type FinishAuthenticationInput struct {
// SessionID is the ceremony session ID returned by BeginAuthentication. Required.
SessionID string
// Response is the raw JSON response payload from navigator.credentials.get().
Response []byte
// Body allows streaming the client JSON response directly from a reader.
Body io.Reader
// ParsedResponse allows supplying pre-parsed credential assertion data.
ParsedResponse *protocol.ParsedCredentialAssertionData
// Session holds optional IP and User-Agent metadata for the issued core session.
Session auth.SessionOptions
}
FinishAuthenticationInput contains client response data for completing authentication.
type FinishRegistrationInput ¶
type FinishRegistrationInput struct {
// SessionID is the ceremony session ID returned by BeginRegistration. Required.
SessionID string
// Response is the raw JSON response payload from navigator.credentials.create().
Response []byte
// Body allows streaming the client JSON response directly from a reader.
Body io.Reader
// ParsedResponse allows supplying pre-parsed credential creation data.
ParsedResponse *protocol.ParsedCredentialCreationData
// FriendlyName optionally overrides the label provided during BeginRegistration.
FriendlyName string
}
FinishRegistrationInput contains client response data for completing registration.
type Hooks ¶
type Hooks struct {
BeforeBeginRegistration func(ctx context.Context, in *BeginRegistrationInput) error
BeforeFinishRegistration func(ctx context.Context, in *FinishRegistrationInput) error
AfterRegistration func(ctx context.Context, cred *Passkey) error
BeforeBeginAuthentication func(ctx context.Context, in *BeginAuthenticationInput) error
BeforeFinishAuthentication func(ctx context.Context, in *FinishAuthenticationInput) error
AfterAuthentication func(ctx context.Context, res *auth.AuthResult) error
}
Hooks provides lifecycle intervention points for passkey operations.
type Module ¶
type Module struct {
// contains filtered or unexported fields
}
Module implements auth.PluginModule for WebAuthn passkey authentication using plugin-sdk.
type Option ¶
type Option func(*Config)
Option applies a configuration option.
func WithChallengeStore ¶
WithChallengeStore sets the transient ceremony challenge store.
func WithEnforceSignCounter ¶
WithEnforceSignCounter toggles sign counter validation and clone rejection.
func WithResidentKey ¶
func WithResidentKey(rk protocol.ResidentKeyRequirement) Option
WithResidentKey configures the resident key / discoverable credential policy.
func WithUserVerification ¶
func WithUserVerification(uv protocol.UserVerificationRequirement) Option
WithUserVerification configures the user verification policy.
type Passkey ¶
type Passkey struct {
ID string `json:"id"`
CredentialID []byte `json:"credential_id"`
UserID string `json:"user_id"`
FriendlyName string `json:"friendly_name"`
PublicKey []byte `json:"public_key"`
AttestationType string `json:"attestation_type"`
AAGUID []byte `json:"aaguid"`
SignCount uint32 `json:"sign_count"`
CloneWarning bool `json:"clone_warning"`
Attachment protocol.AuthenticatorAttachment `json:"attachment"`
Transports []protocol.AuthenticatorTransport `json:"transports"`
UserPresent bool `json:"user_present"`
UserVerified bool `json:"user_verified"`
BackupEligible bool `json:"backup_eligible"`
BackupState bool `json:"backup_state"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
LastUsedAt *time.Time `json:"last_used_at,omitempty"`
RevokedAt *time.Time `json:"revoked_at,omitempty"`
}
Passkey represents a WebAuthn / FIDO2 credential registered by a user.
func FromWebAuthn ¶
FromWebAuthn constructs a domain Passkey from a validated webauthn.Credential.
func (*Passkey) ToWebAuthn ¶
func (c *Passkey) ToWebAuthn() webauthn.Credential
ToWebAuthn converts a Passkey into a webauthn.Credential instance.
type PasskeyRegisteredPayload ¶
type PasskeyRegisteredPayload struct {
UserID string `json:"user_id"`
CredentialID string `json:"credential_id"` // base64url encoded
FriendlyName string `json:"friendly_name"`
AAGUID string `json:"aaguid,omitempty"`
RegisteredAt time.Time `json:"registered_at"`
}
PasskeyRegisteredPayload conveys non-sensitive event metadata when a passkey is registered. Cryptographic keys and raw secrets are strictly excluded.
type PasskeyRevokedPayload ¶
type PasskeyRevokedPayload struct {
UserID string `json:"user_id"`
CredentialID string `json:"credential_id"` // base64url encoded
RevokedAt time.Time `json:"revoked_at"`
}
PasskeyRevokedPayload conveys non-sensitive event metadata when a passkey is revoked.
type PasskeyUsedPayload ¶
type PasskeyUsedPayload struct {
UserID string `json:"user_id"`
CredentialID string `json:"credential_id"` // base64url encoded
SessionID string `json:"session_id"`
UsedAt time.Time `json:"used_at"`
}
PasskeyUsedPayload conveys non-sensitive event metadata when a passkey is used for authentication.
type Passkeys ¶
type Passkeys interface {
// BeginRegistration generates the public key options required by navigator.credentials.create().
BeginRegistration(ctx context.Context, in BeginRegistrationInput) (*RegistrationOptions, error)
// FinishRegistration validates the client response, persists the credential, and links the Core account.
FinishRegistration(ctx context.Context, in FinishRegistrationInput) (*Passkey, error)
// BeginAuthentication generates the options required by navigator.credentials.get().
// Supports both user-specified and discoverable (usernameless / resident key) flows.
BeginAuthentication(ctx context.Context, in BeginAuthenticationInput) (*AuthenticationOptions, error)
// FinishAuthentication verifies the client assertion, checks sign counter replay protection,
// and issues an authenticated session via GoModularAuth Core.
FinishAuthentication(ctx context.Context, in FinishAuthenticationInput) (*auth.AuthResult, error)
// ListCredentials returns all active passkeys registered to the specified user.
ListCredentials(ctx context.Context, userID string) ([]*Passkey, error)
// GetCredential returns a single passkey by credential ID with ownership verification.
GetCredential(ctx context.Context, userID string, credentialID []byte) (*Passkey, error)
// UpdateCredential updates metadata (e.g. friendly name) for an existing passkey.
UpdateCredential(ctx context.Context, in UpdateCredentialInput) (*Passkey, error)
// DeleteCredential revokes/removes the passkey and cleans up its associated Core account.
DeleteCredential(ctx context.Context, in DeleteCredentialInput) error
}
Passkeys is the strongly typed public capability exposed by this plugin. Applications consume it via auth.Get[plugins.Passkeys](a) or auth.Get[passkey.Passkeys](a).
type RegistrationOptions ¶
type RegistrationOptions struct {
// SessionID is the opaque challenge session identifier used to finish registration.
SessionID string `json:"session_id"`
// Options contains the standard WebAuthn PublicKeyCredentialCreationOptions.
Options *protocol.CredentialCreation `json:"options"`
// ExpiresAt specifies when the challenge expires.
ExpiresAt time.Time `json:"expires_at"`
}
RegistrationOptions represents the registration challenge and public key options for the client.
type UpdateCredentialInput ¶
type UpdateCredentialInput struct {
// UserID verifies ownership. Required.
UserID string
// CredentialID is the binary ID of the credential to update. Required.
CredentialID []byte
// FriendlyName is the new label for the passkey.
FriendlyName string
}
UpdateCredentialInput holds parameters for updating passkey metadata.