Documentation
¶
Index ¶
- Variables
- func RegisterPasskeys(api huma.API, passkeyService *PasskeyService, authService *auth.AuthService, ...)
- type AuthTransaction
- type AuthenticationCompletion
- type BeginPasskeyRegistrationInput
- type BeginPasskeyRegistrationOutput
- type BeginStepUpInput
- type BeginStepUpOutput
- type DeletePasskeyInput
- type DeletePasskeyOutput
- type FinishPasskeyRegistrationInput
- type FinishPasskeyRegistrationOutput
- type FinishStepUpInput
- type FinishStepUpOutput
- type GetMFAStatusOutput
- type GetPasskeyCapabilitiesOutput
- type ListMyPasskeysOutput
- type MFARecoveryCodesOutput
- type MFASettingsInput
- type MFAStatus
- type MobilePasskeyExchangeInput
- type MobilePasskeyExchangeOutput
- type MobilePasskeyFinishInput
- type MobilePasskeyFinishOutput
- type Passkey
- type PasskeyCapabilities
- type PasskeyCeremony
- type PasskeyChallenge
- type PasskeyHandler
- func (h *PasskeyHandler) BeginMFA(ctx context.Context, input *PasskeyMFAStartInput) (*PasskeyMFAStartOutput, error)
- func (h *PasskeyHandler) BeginPasskeyLogin(ctx context.Context, _ *struct{}) (*PasskeyLoginBeginOutput, error)
- func (h *PasskeyHandler) BeginRegistration(ctx context.Context, input *BeginPasskeyRegistrationInput) (*BeginPasskeyRegistrationOutput, error)
- func (h *PasskeyHandler) BeginStepUp(ctx context.Context, _ *BeginStepUpInput) (*BeginStepUpOutput, error)
- func (h *PasskeyHandler) DeletePasskey(ctx context.Context, input *DeletePasskeyInput) (*DeletePasskeyOutput, error)
- func (h *PasskeyHandler) DisableMFA(ctx context.Context, input *MFASettingsInput) (*DeletePasskeyOutput, error)
- func (h *PasskeyHandler) EnableMFA(ctx context.Context, input *MFASettingsInput) (*MFARecoveryCodesOutput, error)
- func (h *PasskeyHandler) ExchangeMobilePasskeyLogin(ctx context.Context, input *MobilePasskeyExchangeInput) (*MobilePasskeyExchangeOutput, error)
- func (h *PasskeyHandler) FinishMFA(ctx context.Context, input *PasskeyMFAFinishInput) (*PasskeyMFAFinishOutput, error)
- func (h *PasskeyHandler) FinishMobilePasskeyLogin(ctx context.Context, input *MobilePasskeyFinishInput) (*MobilePasskeyFinishOutput, error)
- func (h *PasskeyHandler) FinishPasskeyLogin(ctx context.Context, input *PasskeyLoginFinishInput) (*PasskeyLoginFinishOutput, error)
- func (h *PasskeyHandler) FinishRegistration(ctx context.Context, input *FinishPasskeyRegistrationInput) (*FinishPasskeyRegistrationOutput, error)
- func (h *PasskeyHandler) FinishStepUp(ctx context.Context, input *FinishStepUpInput) (*FinishStepUpOutput, error)
- func (h *PasskeyHandler) GetCapabilities(ctx context.Context, _ *struct{}) (*GetPasskeyCapabilitiesOutput, error)
- func (h *PasskeyHandler) GetMFAStatus(ctx context.Context, _ *struct{}) (*GetMFAStatusOutput, error)
- func (h *PasskeyHandler) ListMyPasskeys(ctx context.Context, _ *struct{}) (*ListMyPasskeysOutput, error)
- func (h *PasskeyHandler) PasswordStepUp(ctx context.Context, input *PasswordStepUpInput) (*PasswordStepUpOutput, error)
- func (h *PasskeyHandler) RegenerateRecoveryCodes(ctx context.Context, input *MFASettingsInput) (*MFARecoveryCodesOutput, error)
- func (h *PasskeyHandler) RenamePasskey(ctx context.Context, input *RenamePasskeyInput) (*RenamePasskeyOutput, error)
- func (h *PasskeyHandler) UseRecoveryCode(ctx context.Context, input *PasskeyRecoveryInput) (*PasskeyRecoveryOutput, error)
- type PasskeyLoginBeginOutput
- type PasskeyLoginFinishInput
- type PasskeyLoginFinishOutput
- type PasskeyMFAFinishInput
- type PasskeyMFAFinishOutput
- type PasskeyMFAStartInput
- type PasskeyMFAStartOutput
- type PasskeyRecoveryCode
- type PasskeyRecoveryInput
- type PasskeyRecoveryOutput
- type PasskeyService
- type PasskeySummary
- type PasswordStepUpInput
- type PasswordStepUpOutput
- type RecoveryCodesResponse
- type RenamePasskeyInput
- type RenamePasskeyOutput
- type StepUpGrant
Constants ¶
This section is empty.
Variables ¶
var ( ErrPasskeyCeremony = errors.Sentinel("invalid or expired passkey ceremony") ErrPasskeyTransaction = errors.Sentinel("invalid or expired authentication transaction") ErrPasskeyResponse = errors.Sentinel("invalid passkey response") ErrPasskeyNotFound = errors.Sentinel("passkey not found") ErrPasskeyExists = errors.Sentinel("passkey already registered") ErrPasskeyStepUpRequired = errors.Sentinel("fresh step-up authentication is required") ErrPasskeyMFAEnabled = errors.Sentinel("passkey MFA must be disabled first") ErrPasskeyMFAAlreadyEnabled = errors.Sentinel("passkey MFA is already enabled") ErrPasskeyMFANotEnabled = errors.Sentinel("passkey MFA is not enabled") ErrPasskeyNoCredential = errors.Sentinel("no passkeys are registered") ErrPasskeyLastCredential = errors.Sentinel("cannot remove the last usable authentication method") ErrPasskeyRecoveryCode = errors.Sentinel("invalid recovery code") ErrPasskeyName = errors.Sentinel("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 *common.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 BeginPasskeyRegistrationOutput ¶
type BeginPasskeyRegistrationOutput struct {
Body base.ApiResponse[passkeyBeginResponse]
}
type BeginStepUpInput ¶
type BeginStepUpInput struct{}
type BeginStepUpOutput ¶
type BeginStepUpOutput struct {
Body base.ApiResponse[passkeyBeginResponse]
}
type DeletePasskeyInput ¶
type DeletePasskeyOutput ¶
type DeletePasskeyOutput struct {
Body base.ApiResponse[base.MessageResponse]
}
type FinishPasskeyRegistrationInput ¶
type FinishPasskeyRegistrationInput struct {
UserAgent string `header:"User-Agent"`
Body passkeyCredentialBody
}
type FinishPasskeyRegistrationOutput ¶
type FinishPasskeyRegistrationOutput struct {
Body base.ApiResponse[PasskeySummary]
}
type FinishStepUpInput ¶
type FinishStepUpInput struct {
Body stepUpFinishBody
}
type FinishStepUpOutput ¶
type FinishStepUpOutput struct {
Body base.ApiResponse[StepUpGrant]
}
type GetMFAStatusOutput ¶
type GetMFAStatusOutput struct {
Body base.ApiResponse[MFAStatus]
}
type GetPasskeyCapabilitiesOutput ¶
type GetPasskeyCapabilitiesOutput struct {
Body base.ApiResponse[PasskeyCapabilities]
}
type ListMyPasskeysOutput ¶
type ListMyPasskeysOutput struct {
Body base.ApiResponse[[]PasskeySummary]
}
type MFARecoveryCodesOutput ¶
type MFARecoveryCodesOutput struct {
Body base.ApiResponse[RecoveryCodesResponse]
}
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 {
SetCookie []string `header:"Set-Cookie" doc:"Session cookie"`
Body base.ApiResponse[authtypes.AuthenticationResponse]
}
type MobilePasskeyFinishInput ¶
type MobilePasskeyFinishInput struct {
Body mobilePasskeyFinishBody
}
type MobilePasskeyFinishOutput ¶
type MobilePasskeyFinishOutput struct {
Body base.ApiResponse[authtypes.MobilePasskeyCompletion]
}
type Passkey ¶ added in v2.8.1
type Passkey struct {
database.BaseModel
UserID string `json:"userId" gorm:"column:user_id;not null;index"`
User *common.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.
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 (h *PasskeyHandler) BeginMFA(ctx context.Context, input *PasskeyMFAStartInput) (*PasskeyMFAStartOutput, error)
func (*PasskeyHandler) BeginPasskeyLogin ¶
func (h *PasskeyHandler) BeginPasskeyLogin(ctx context.Context, _ *struct{}) (*PasskeyLoginBeginOutput, error)
func (*PasskeyHandler) BeginRegistration ¶
func (h *PasskeyHandler) BeginRegistration(ctx context.Context, input *BeginPasskeyRegistrationInput) (*BeginPasskeyRegistrationOutput, error)
func (*PasskeyHandler) BeginStepUp ¶
func (h *PasskeyHandler) BeginStepUp(ctx context.Context, _ *BeginStepUpInput) (*BeginStepUpOutput, error)
func (*PasskeyHandler) DeletePasskey ¶
func (h *PasskeyHandler) DeletePasskey(ctx context.Context, input *DeletePasskeyInput) (*DeletePasskeyOutput, error)
func (*PasskeyHandler) DisableMFA ¶
func (h *PasskeyHandler) DisableMFA(ctx context.Context, input *MFASettingsInput) (*DeletePasskeyOutput, error)
func (*PasskeyHandler) EnableMFA ¶
func (h *PasskeyHandler) EnableMFA(ctx context.Context, input *MFASettingsInput) (*MFARecoveryCodesOutput, error)
func (*PasskeyHandler) ExchangeMobilePasskeyLogin ¶
func (h *PasskeyHandler) ExchangeMobilePasskeyLogin(ctx context.Context, input *MobilePasskeyExchangeInput) (*MobilePasskeyExchangeOutput, error)
func (*PasskeyHandler) FinishMFA ¶
func (h *PasskeyHandler) FinishMFA(ctx context.Context, input *PasskeyMFAFinishInput) (*PasskeyMFAFinishOutput, error)
func (*PasskeyHandler) FinishMobilePasskeyLogin ¶
func (h *PasskeyHandler) FinishMobilePasskeyLogin(ctx context.Context, input *MobilePasskeyFinishInput) (*MobilePasskeyFinishOutput, error)
func (*PasskeyHandler) FinishPasskeyLogin ¶
func (h *PasskeyHandler) FinishPasskeyLogin(ctx context.Context, input *PasskeyLoginFinishInput) (*PasskeyLoginFinishOutput, error)
func (*PasskeyHandler) FinishRegistration ¶
func (h *PasskeyHandler) FinishRegistration(ctx context.Context, input *FinishPasskeyRegistrationInput) (*FinishPasskeyRegistrationOutput, error)
func (*PasskeyHandler) FinishStepUp ¶
func (h *PasskeyHandler) FinishStepUp(ctx context.Context, input *FinishStepUpInput) (*FinishStepUpOutput, error)
func (*PasskeyHandler) GetCapabilities ¶
func (h *PasskeyHandler) GetCapabilities(ctx context.Context, _ *struct{}) (*GetPasskeyCapabilitiesOutput, error)
func (*PasskeyHandler) GetMFAStatus ¶
func (h *PasskeyHandler) GetMFAStatus(ctx context.Context, _ *struct{}) (*GetMFAStatusOutput, error)
func (*PasskeyHandler) ListMyPasskeys ¶
func (h *PasskeyHandler) ListMyPasskeys(ctx context.Context, _ *struct{}) (*ListMyPasskeysOutput, error)
func (*PasskeyHandler) PasswordStepUp ¶
func (h *PasskeyHandler) PasswordStepUp(ctx context.Context, input *PasswordStepUpInput) (*PasswordStepUpOutput, error)
func (*PasskeyHandler) RegenerateRecoveryCodes ¶
func (h *PasskeyHandler) RegenerateRecoveryCodes(ctx context.Context, input *MFASettingsInput) (*MFARecoveryCodesOutput, error)
func (*PasskeyHandler) RenamePasskey ¶
func (h *PasskeyHandler) RenamePasskey(ctx context.Context, input *RenamePasskeyInput) (*RenamePasskeyOutput, error)
func (*PasskeyHandler) UseRecoveryCode ¶
func (h *PasskeyHandler) UseRecoveryCode(ctx context.Context, input *PasskeyRecoveryInput) (*PasskeyRecoveryOutput, error)
type PasskeyLoginBeginOutput ¶
type PasskeyLoginBeginOutput struct {
Body base.ApiResponse[passkeyBeginResponse]
}
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 PasskeyMFAStartOutput ¶
type PasskeyMFAStartOutput struct {
Body base.ApiResponse[authtypes.MFAChallenge]
}
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 = passkeyService
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
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 PasswordStepUpOutput ¶
type PasswordStepUpOutput struct {
Body base.ApiResponse[StepUpGrant]
}
type RecoveryCodesResponse ¶
type RecoveryCodesResponse struct {
Codes []string `json:"codes" doc:"Recovery codes; shown only once"`
}
type RenamePasskeyInput ¶
type RenamePasskeyOutput ¶
type RenamePasskeyOutput struct {
Body base.ApiResponse[PasskeySummary]
}
type StepUpGrant ¶
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.