Help us shape the future of Go! Take the 2026 Go Developer Survey

passkey

package
v2.17.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 31, 2026 License: BSD-3-Clause Imports: 37 Imported by: 0

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrPasskeyServiceUnavailable = errors.New("passkey service is unavailable")
	ErrPasskeyCeremony           = errors.New("invalid or expired passkey ceremony")
	ErrPasskeyTransaction        = errors.New("invalid or expired authentication transaction")
	ErrPasskeyResponse           = errors.New("invalid passkey response")
	ErrPasskeyNotFound           = errors.New("passkey not found")
	ErrPasskeyExists             = errors.New("passkey already registered")
	ErrPasskeyStepUpRequired     = errors.New("fresh step-up authentication is required")
	ErrPasskeyMFAEnabled         = errors.New("passkey MFA must be disabled first")
	ErrPasskeyMFAAlreadyEnabled  = errors.New("passkey MFA is already enabled")
	ErrPasskeyMFANotEnabled      = errors.New("passkey MFA is not enabled")
	ErrPasskeyNoCredential       = errors.New("no passkeys are registered")
	ErrPasskeyLastCredential     = errors.New("cannot remove the last usable authentication method")
	ErrPasskeyRecoveryCode       = errors.New("invalid recovery code")
	ErrPasskeyName               = errors.New("invalid passkey name")
)

Functions

func RegisterPasskeys

func RegisterPasskeys(api huma.API, passkeyService *PasskeyService, authService *auth.AuthService, userService *user.UserService)

Types

type AuthTransaction added in v2.8.1

type AuthTransaction struct {
	database.BaseModel

	Kind        string     `json:"kind" gorm:"column:kind;not null;index"`
	UserID      string     `json:"userId" gorm:"column:user_id;not null;index"`
	SessionID   *string    `json:"sessionId,omitempty" gorm:"column:session_id;index"`
	Source      string     `json:"source" gorm:"column:source;not null"`
	UserAgent   *string    `json:"-" gorm:"column:user_agent"`
	IPAddress   *string    `json:"-" gorm:"column:ip_address"`
	SecretHash  *string    `json:"-" gorm:"column:secret_hash;index"`
	Status      string     `json:"status" gorm:"column:status;not null;index"`
	ExpiresAt   time.Time  `json:"expiresAt" gorm:"column:expires_at;not null;index"`
	CompletedAt *time.Time `json:"completedAt,omitempty" gorm:"column:completed_at"`
}

AuthTransaction links a primary authentication result to its pending passkey MFA or step-up ceremony. The client receives only ID/secret values; primary credentials and WebAuthn SessionData remain server-side.

func (AuthTransaction) TableName added in v2.8.1

func (AuthTransaction) TableName() string

type AuthenticationCompletion

type AuthenticationCompletion struct {
	User   *userdomain.User
	Meta   auth.SessionMeta
	Source string
}

AuthenticationCompletion carries the original primary-auth metadata across an MFA transaction so the eventual session cannot be assigned client-chosen source or network metadata.

type BeginPasskeyRegistrationInput

type BeginPasskeyRegistrationInput struct {
	StepUpToken string `header:"X-Step-Up-Token"`
}

type BeginStepUpInput

type BeginStepUpInput struct{}

type DeletePasskeyInput

type DeletePasskeyInput struct {
	ID          string `path:"id"`
	StepUpToken string `header:"X-Step-Up-Token"`
}

type FinishPasskeyRegistrationInput

type FinishPasskeyRegistrationInput struct {
	UserAgent string `header:"User-Agent"`
	Body      passkeyCredentialBody
}

type FinishStepUpInput

type FinishStepUpInput struct {
	Body stepUpFinishBody
}

type MFASettingsInput

type MFASettingsInput struct {
	StepUpToken string `header:"X-Step-Up-Token"`
}

type MFAStatus

type MFAStatus struct {
	Enabled                bool `json:"enabled"`
	PasskeyCount           int  `json:"passkeyCount"`
	RecoveryCodesRemaining int  `json:"recoveryCodesRemaining"`
}

MFAStatus is the account's passkey MFA state. Recovery codes are counted, but their plaintext values are never returned after generation.

type MobilePasskeyExchangeInput

type MobilePasskeyExchangeInput struct {
	UserAgent string `header:"User-Agent"`
	Body      mobilePasskeyExchangeBody
}

type MobilePasskeyExchangeOutput

type MobilePasskeyExchangeOutput struct {
	Body base.ApiResponse[authtypes.AuthenticationResponse]
}

type MobilePasskeyFinishInput

type MobilePasskeyFinishInput struct {
	Body mobilePasskeyFinishBody
}

type Passkey added in v2.8.1

type Passkey struct {
	database.BaseModel

	UserID string     `json:"userId" gorm:"column:user_id;not null;index"`
	User   *user.User `json:"-" gorm:"foreignKey:UserID;constraint:OnDelete:CASCADE"`

	RPID                    string               `json:"rpId" gorm:"column:rp_id;not null"`
	CredentialID            []byte               `json:"-" gorm:"column:credential_id;not null"`
	PublicKey               []byte               `json:"-" gorm:"column:public_key;not null"`
	AttestationType         string               `json:"attestationType,omitempty" gorm:"column:attestation_type"`
	AttestationFormat       string               `json:"attestationFormat,omitempty" gorm:"column:attestation_format"`
	Transports              database.StringSlice `json:"transports,omitempty" gorm:"column:transports;type:text"`
	AAGUID                  []byte               `json:"-" gorm:"column:aaguid"`
	SignCount               uint32               `json:"signCount" gorm:"column:sign_count;not null;default:0"`
	BackupEligible          bool                 `json:"backupEligible" gorm:"column:backup_eligible;not null;default:false"`
	BackupState             bool                 `json:"backupState" gorm:"column:backup_state;not null;default:false"`
	CloneWarning            bool                 `json:"cloneWarning" gorm:"column:clone_warning;not null;default:false"`
	AuthenticatorAttachment string               `json:"authenticatorAttachment,omitempty" gorm:"column:authenticator_attachment"`

	AttestationClientDataJSON     []byte `json:"-" gorm:"column:attestation_client_data_json"`
	AttestationClientDataHash     []byte `json:"-" gorm:"column:attestation_client_data_hash"`
	AttestationAuthenticatorData  []byte `json:"-" gorm:"column:attestation_authenticator_data"`
	AttestationPublicKeyAlgorithm int64  `json:"-" gorm:"column:attestation_public_key_algorithm"`
	AttestationObject             []byte `json:"-" gorm:"column:attestation_object"`

	Name       string     `json:"name" gorm:"column:name;not null"`
	LastUsedAt *time.Time `json:"lastUsedAt,omitempty" gorm:"column:last_used_at"`
}

Passkey stores the WebAuthn credential record required to validate future assertions. The raw attestation fields are retained so the credential can be audited or revalidated if the WebAuthn library's verification policy evolves.

func (Passkey) TableName added in v2.8.1

func (Passkey) TableName() string

type PasskeyCapabilities

type PasskeyCapabilities struct {
	PasskeyMFAEnabled          bool `json:"passkeyMfaEnabled"`
	PasskeyCount               int  `json:"passkeyCount"`
	HasLocalPassword           bool `json:"hasLocalPassword"`
	HasOIDCFallback            bool `json:"hasOidcFallback"`
	CanEnrollWithActiveSession bool `json:"canEnrollWithActiveSession"`
	CanDeleteLastPasskey       bool `json:"canDeleteLastPasskey"`
	RequiresStepUp             bool `json:"requiresStepUp"`
}

PasskeyCapabilities describes the server-derived authentication choices for the current account. It deliberately does not trust client-supplied flags.

type PasskeyCeremony added in v2.8.1

type PasskeyCeremony struct {
	database.BaseModel

	Purpose           string     `json:"purpose" gorm:"column:purpose;not null;index"`
	UserID            *string    `json:"userId,omitempty" gorm:"column:user_id;index"`
	SessionID         *string    `json:"sessionId,omitempty" gorm:"column:session_id;index"`
	AuthTransactionID *string    `json:"authTransactionId,omitempty" gorm:"column:auth_transaction_id;index"`
	RPID              string     `json:"rpId" gorm:"column:rp_id;not null"`
	SessionData       string     `json:"-" gorm:"column:session_data;type:text;not null"`
	ExpiresAt         time.Time  `json:"expiresAt" gorm:"column:expires_at;not null;index"`
	ConsumedAt        *time.Time `json:"-" gorm:"column:consumed_at;index"`
}

PasskeyCeremony holds the opaque server-side state between WebAuthn begin and finish calls. It is intentionally never serialized to the client.

func (PasskeyCeremony) TableName added in v2.8.1

func (PasskeyCeremony) TableName() string

type PasskeyChallenge

type PasskeyChallenge struct {
	CeremonyID    string
	TransactionID string
	Options       any
	ExpiresAt     time.Time
}

PasskeyChallenge is the public result of a WebAuthn ceremony begin. The matching SessionData remains in passkey_ceremonies.

type PasskeyHandler

type PasskeyHandler struct {
	// contains filtered or unexported fields
}

func (*PasskeyHandler) BeginMFA

func (*PasskeyHandler) BeginPasskeyLogin

func (h *PasskeyHandler) BeginPasskeyLogin(ctx context.Context, _ *struct{}) (*handlerutil.Out[passkeyBeginResponse], error)

func (*PasskeyHandler) BeginRegistration

func (h *PasskeyHandler) BeginRegistration(ctx context.Context, input *BeginPasskeyRegistrationInput) (*handlerutil.Out[passkeyBeginResponse], error)

func (*PasskeyHandler) BeginStepUp

func (h *PasskeyHandler) BeginStepUp(ctx context.Context, _ *BeginStepUpInput) (*handlerutil.Out[passkeyBeginResponse], error)

func (*PasskeyHandler) DeletePasskey

func (*PasskeyHandler) DisableMFA

func (*PasskeyHandler) EnableMFA

func (*PasskeyHandler) ExchangeMobilePasskeyLogin

func (h *PasskeyHandler) ExchangeMobilePasskeyLogin(ctx context.Context, input *MobilePasskeyExchangeInput) (*MobilePasskeyExchangeOutput, error)

func (*PasskeyHandler) FinishMFA

func (*PasskeyHandler) FinishMobilePasskeyLogin

func (*PasskeyHandler) FinishPasskeyLogin

func (*PasskeyHandler) FinishRegistration

func (*PasskeyHandler) FinishStepUp

func (h *PasskeyHandler) FinishStepUp(ctx context.Context, input *FinishStepUpInput) (*handlerutil.Out[StepUpGrant], error)

func (*PasskeyHandler) GetCapabilities

func (h *PasskeyHandler) GetCapabilities(ctx context.Context, _ *struct{}) (*handlerutil.Out[PasskeyCapabilities], error)

func (*PasskeyHandler) GetMFAStatus

func (h *PasskeyHandler) GetMFAStatus(ctx context.Context, _ *struct{}) (*handlerutil.Out[MFAStatus], error)

func (*PasskeyHandler) ListMyPasskeys

func (h *PasskeyHandler) ListMyPasskeys(ctx context.Context, _ *struct{}) (*handlerutil.Out[[]PasskeySummary], error)

func (*PasskeyHandler) PasswordStepUp

func (h *PasskeyHandler) PasswordStepUp(ctx context.Context, input *PasswordStepUpInput) (*handlerutil.Out[StepUpGrant], error)

func (*PasskeyHandler) RegenerateRecoveryCodes

func (h *PasskeyHandler) RegenerateRecoveryCodes(ctx context.Context, input *MFASettingsInput) (*handlerutil.Out[RecoveryCodesResponse], error)

func (*PasskeyHandler) RenamePasskey

func (*PasskeyHandler) UseRecoveryCode

func (h *PasskeyHandler) UseRecoveryCode(ctx context.Context, input *PasskeyRecoveryInput) (*PasskeyRecoveryOutput, error)

type PasskeyLoginFinishInput

type PasskeyLoginFinishInput struct {
	UserAgent string `header:"User-Agent"`
	Body      passkeyCredentialBody
}

type PasskeyLoginFinishOutput

type PasskeyLoginFinishOutput struct {
	SetCookie []string `header:"Set-Cookie" doc:"Session cookie"`
	Body      base.ApiResponse[authtypes.AuthenticationResponse]
}

type PasskeyMFAFinishInput

type PasskeyMFAFinishInput struct {
	Body mfaFinishBody
}

type PasskeyMFAFinishOutput

type PasskeyMFAFinishOutput struct {
	SetCookie []string `header:"Set-Cookie" doc:"Session cookie"`
	Body      base.ApiResponse[authtypes.AuthenticationResponse]
}

type PasskeyMFAStartInput

type PasskeyMFAStartInput struct {
	Body mfaBeginBody
}

type PasskeyRecoveryCode added in v2.8.1

type PasskeyRecoveryCode struct {
	database.BaseModel

	UserID   string     `json:"userId" gorm:"column:user_id;not null;index"`
	CodeHash string     `json:"-" gorm:"column:code_hash;not null;uniqueIndex"`
	UsedAt   *time.Time `json:"usedAt,omitempty" gorm:"column:used_at;index"`
}

PasskeyRecoveryCode stores only a one-way digest of a recovery code. The plaintext is returned once during generation and is never recoverable.

func (PasskeyRecoveryCode) TableName added in v2.8.1

func (PasskeyRecoveryCode) TableName() string

type PasskeyRecoveryInput

type PasskeyRecoveryInput struct {
	Body recoveryBody
}

type PasskeyRecoveryOutput

type PasskeyRecoveryOutput struct {
	SetCookie []string `header:"Set-Cookie" doc:"Session cookie"`
	Body      base.ApiResponse[authtypes.AuthenticationResponse]
}

type PasskeyService

type PasskeyService struct {
	// contains filtered or unexported fields
}

PasskeyService owns WebAuthn ceremonies, passkey persistence, MFA transactions, recovery codes, and step-up grants. It intentionally does not issue JWTs; auth.AuthService remains the single token/session issuer.

func NewPasskeyService

func NewPasskeyService(db *database.DB, cfg *config.Config) *PasskeyService

func (*PasskeyService) BeginMFAAuthentication added in v2.15.0

func (s *PasskeyService) BeginMFAAuthentication(ctx context.Context, userID string, meta auth.SessionMeta, source string) (*auth.MFAChallenge, error)

func (*PasskeyService) BeginMFAForTransaction added in v2.15.0

func (s *PasskeyService) BeginMFAForTransaction(ctx context.Context, transactionID string) (*auth.MFAChallenge, error)

BeginMFAForTransaction starts a passkey assertion for an already-created pending MFA transaction. This is useful to clients that separate primary authentication from challenge retrieval.

func (*PasskeyService) BeginPasskeyLogin added in v2.15.0

func (s *PasskeyService) BeginPasskeyLogin(ctx context.Context) (*PasskeyChallenge, error)

func (*PasskeyService) BeginRegistration added in v2.15.0

func (s *PasskeyService) BeginRegistration(ctx context.Context, userID, sessionID, stepUpToken string) (*PasskeyChallenge, error)

func (*PasskeyService) BeginStepUp added in v2.15.0

func (s *PasskeyService) BeginStepUp(ctx context.Context, userID, sessionID string, meta auth.SessionMeta) (*PasskeyChallenge, error)

func (*PasskeyService) CreatePasswordStepUpGrant added in v2.15.0

func (s *PasskeyService) CreatePasswordStepUpGrant(ctx context.Context, userID, sessionID string) (*StepUpGrant, error)

func (*PasskeyService) DeletePasskey added in v2.15.0

func (s *PasskeyService) DeletePasskey(ctx context.Context, userID, passkeyID, sessionID, stepUpToken string, oidcFallbackAllowed bool) error

func (*PasskeyService) DisableMFA added in v2.15.0

func (s *PasskeyService) DisableMFA(ctx context.Context, userID, sessionID, stepUpToken string) error

func (*PasskeyService) EnableMFA added in v2.15.0

func (s *PasskeyService) EnableMFA(ctx context.Context, userID, sessionID, stepUpToken string) ([]string, error)

func (*PasskeyService) ExchangeMobilePasskeyLogin added in v2.15.0

func (s *PasskeyService) ExchangeMobilePasskeyLogin(ctx context.Context, transactionID, codeVerifier string) (*userdomain.User, error)

func (*PasskeyService) FinishMFA added in v2.15.0

func (s *PasskeyService) FinishMFA(ctx context.Context, transactionID string, payload []byte) (*AuthenticationCompletion, error)

func (*PasskeyService) FinishMobilePasskeyLogin added in v2.15.0

func (s *PasskeyService) FinishMobilePasskeyLogin(ctx context.Context, ceremonyID string, payload []byte, codeChallenge string) (*auth.MobilePasskeyCompletion, error)

func (*PasskeyService) FinishPasskeyLogin added in v2.15.0

func (s *PasskeyService) FinishPasskeyLogin(ctx context.Context, ceremonyID string, payload []byte) (*userdomain.User, error)

func (*PasskeyService) FinishRecoveryCode added in v2.15.0

func (s *PasskeyService) FinishRecoveryCode(ctx context.Context, transactionID, code string) (*AuthenticationCompletion, error)

func (*PasskeyService) FinishRegistration added in v2.15.0

func (s *PasskeyService) FinishRegistration(ctx context.Context, userID, sessionID, ceremonyID string, payload []byte, name string) (*PasskeySummary, error)

func (*PasskeyService) FinishStepUp added in v2.15.0

func (s *PasskeyService) FinishStepUp(ctx context.Context, transactionID, sessionID string, payload []byte) (*StepUpGrant, error)

func (*PasskeyService) GetCapabilities added in v2.15.0

func (s *PasskeyService) GetCapabilities(ctx context.Context, userID string, oidcEnabled bool) (*PasskeyCapabilities, error)

func (*PasskeyService) GetMFAStatus added in v2.15.0

func (s *PasskeyService) GetMFAStatus(ctx context.Context, userID string) (*MFAStatus, error)

func (*PasskeyService) ListPasskeys added in v2.15.0

func (s *PasskeyService) ListPasskeys(ctx context.Context, userID string) ([]PasskeySummary, error)

func (*PasskeyService) LoginAvailable added in v2.15.0

func (s *PasskeyService) LoginAvailable(ctx context.Context) (bool, error)

LoginAvailable reports whether a registered passkey can be used on this instance.

func (*PasskeyService) RegenerateRecoveryCodes added in v2.15.0

func (s *PasskeyService) RegenerateRecoveryCodes(ctx context.Context, userID, sessionID, stepUpToken string) ([]string, error)

func (*PasskeyService) RenamePasskey added in v2.15.0

func (s *PasskeyService) RenamePasskey(ctx context.Context, userID, passkeyID, name, sessionID, stepUpToken string) (*PasskeySummary, error)

func (*PasskeyService) ResetMFAForUser added in v2.15.0

func (s *PasskeyService) ResetMFAForUser(ctx context.Context, userID string) error

ResetMFAForUser is intentionally separate from self-service operations. It is used only by the explicitly gated embedded admin recovery command.

func (*PasskeyService) VerifyStepUpToken added in v2.15.0

func (s *PasskeyService) VerifyStepUpToken(ctx context.Context, userID, sessionID, token string) error

VerifyStepUpToken accepts a grant repeatedly until it expires, so a single re-authentication covers a short run of management actions instead of one. The grant stays bound to the issuing user and session.

type PasskeySummary

type PasskeySummary struct {
	ID                      string     `json:"id"`
	Name                    string     `json:"name"`
	RPID                    string     `json:"rpId"`
	AAGUID                  string     `json:"aaguid,omitempty"`
	Transports              []string   `json:"transports,omitempty"`
	BackupEligible          bool       `json:"backupEligible"`
	BackupState             bool       `json:"backupState"`
	CloneWarning            bool       `json:"cloneWarning"`
	AuthenticatorAttachment string     `json:"authenticatorAttachment,omitempty"`
	CreatedAt               time.Time  `json:"createdAt"`
	UpdatedAt               *time.Time `json:"updatedAt,omitempty"`
	LastUsedAt              *time.Time `json:"lastUsedAt,omitempty"`
}

PasskeySummary is the safe representation of a stored credential.

type PasswordStepUpInput

type PasswordStepUpInput struct {
	Body passwordReauthBody
}

type RecoveryCodesResponse

type RecoveryCodesResponse struct {
	Codes []string `json:"codes" doc:"Recovery codes; shown only once"`
}

type RenamePasskeyInput

type RenamePasskeyInput struct {
	ID          string `path:"id"`
	StepUpToken string `header:"X-Step-Up-Token"`
	Body        renamePasskeyBody
}

type StepUpGrant

type StepUpGrant struct {
	Token     string    `json:"token"`
	ExpiresAt time.Time `json:"expiresAt"`
}

StepUpGrant is returned after a fresh password or passkey assertion. The token is hashed in the database and stays usable, for the issuing session only, until ExpiresAt.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL