authflow

package
v1.0.2 Latest Latest
Warning

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

Go to latest
Published: Sep 30, 2026 License: MIT Imports: 10 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ActionUpdateUsername       = "update_username"
	ActionRequestPasswordReset = "request_password_reset"
	ActionRequestVerification  = "request_verification"
)

ActionAvailability reports whether a cooldown-gated action is currently allowed; it rides on 429 error metadata. Action names carried by ActionAvailability.

View Source
const SensitiveActionFreshAuthWindow = 15 * time.Minute

Variables

This section is empty.

Functions

func NewTokenSet added in v1.0.2

func NewTokenSet(access, refresh string, exp time.Time) iam.TokenSet

NewTokenSet builds a Bearer TokenSet whose expires_in is derived from exp; an empty refresh token is none.

func NormalizeAuthMethods

func NormalizeAuthMethods(methods []string) []string

func NormalizePreferredLanguage

func NormalizePreferredLanguage(language string) (string, error)

NormalizePreferredLanguage is lang.Normalize for an account's stored preference: "" clears it, and a value naming no language is refused.

func RecentSignIn

func RecentSignIn(authTime time.Time, amr []string, mfa bool, now time.Time) bool

RecentSignIn reports whether a token's assurance clears the sensitive-action gate: signed in within SensitiveActionFreshAuthWindow and, for an account with a usable second factor (mfa), with that factor (amr otp or mfa). An account without one is never blocked for lacking it.

func SessionRevokeReasonFrom

func SessionRevokeReasonFrom(ctx context.Context) *string

SessionRevokeReasonFrom reads the reason WithSessionRevokeReason attached, or nil.

func StepUpMethods

func StepUpMethods(hasPassword bool, settings *TwoFactorSettings, providerSlugs []string, supportsStepUp func(string) bool) []string

StepUpMethods lists how the user can re-authenticate for a sensitive action: password, an enabled second factor, and every linked provider that supports step-up (de-duplicated, sorted). Pure over already-loaded inputs.

func ValidTwoFactorStepUpMethod

func ValidTwoFactorStepUpMethod(method string) bool

ValidTwoFactorStepUpMethod reports whether method can satisfy a step-up.

func ValidationErrorCode

func ValidationErrorCode(err error) errmodel.Code

ValidationErrorCode returns the identity-policy code err carries, or "" when err is not a validation failure.

func WithSessionRevokeReason

func WithSessionRevokeReason(ctx context.Context, reason SessionRevokeReason) context.Context

WithSessionRevokeReason annotates ctx so revoke paths can record a structured reason in the session log.

Types

type AccountRecoveryConfirmation

type AccountRecoveryConfirmation struct {
	Token     string    `json:"token"`
	ExpiresAt time.Time `json:"expires_at"`
	PurgeAt   time.Time `json:"purge_at"`
}

AccountRecoveryConfirmation is an opaque proof, never an access token or session. Confirmation restores this deletion generation without signing in.

type ActionAvailability

type ActionAvailability = errmodel.ActionAvailability

type AuthSessionEvent

type AuthSessionEvent struct {
	OccurredAt time.Time
	Issuer     string
	UserID     string
	SessionID  string
	Event      iam.SessionEventKind
	Method     *string
	Reason     *string
	IPAddr     *string
	UserAgent  *string
}

AuthSessionEvent is a best-effort, append-only session lifecycle record stored in Postgres (session_events, #245) and retained per Config.SessionEventRetention. issuer/user_id/session_id/event are required; method is typically set for SessionEventCreated and reason for SessionEventRevoked.

type DeviceKeyAuthResult

type DeviceKeyAuthResult struct {
	UserID      string
	AccessToken string
	ExpiresAt   time.Time
	DeviceKey   iam.DeviceKey
}

DeviceKeyAuthResult is a device key's sign-in: its account, access token and key.

type DeviceKeyChallenge

type DeviceKeyChallenge struct {
	ID        string
	Challenge string
	ExpiresAt time.Time
}

DeviceKey is the public projection of one native-client credential.

type DeviceKeySecondFactorRequired

type DeviceKeySecondFactorRequired struct{ Method string }

DeviceKeySecondFactorRequired is returned by FinishDeviceKeyEnrollment when the email code and key proof are valid but the account has a usable second factor that was not presented (#293). Method is a factor independent of the enrollment mailbox (totp, sms) or backup_code. The ceremony stays live for a retry carrying the code; for an SMS factor the code has just been sent.

func (*DeviceKeySecondFactorRequired) Error

type ExternalIdentity

type ExternalIdentity struct {
	Provider          string // provider slug (the configured name)
	Issuer            string
	Subject           string
	Email             string
	EmailVerified     bool
	PreferredUsername string
	DisplayName       string
}

ExternalIdentity is a provider-verified identity.

type ExternalLinkAuthorization

type ExternalLinkAuthorization struct {
	UserID          string
	SessionID       string
	AuthenticatedAt time.Time
}

ExternalLinkAuthorization records the fresh session that initiated linking. It is carried only in server-side browser state, never accepted from a callback.

type ExternalLoginInput

type ExternalLoginInput struct {
	Identity ExternalIdentity
	// Link authorizes a provider mutation only; it never creates a session.
	Link               *ExternalLinkAuthorization
	AccountInviteToken string
	// ReturnTo is where the browser flow began; the sign-in's continuations
	// carry it to their AuthResult.
	ReturnTo  string
	Event     string // session-created audit event, e.g. "oidc_login"
	UserAgent string
	IP        string
}

ExternalLoginInput is an external-identity login or link attempt.

type FactorEnrollmentMode

type FactorEnrollmentMode string

FactorEnrollmentMode distinguishes restricted enrollment grants from authenticated factor management.

const (
	// FirstFactorOnly permits a restricted grant to enroll only when no factor exists.
	FirstFactorOnly FactorEnrollmentMode = "first_factor_only"
	// AllowAdditionalFactors permits fresh authenticated users to add a new method.
	AllowAdditionalFactors FactorEnrollmentMode = "allow_additional_factors"
)

type FreshAuth added in v0.149.0

type FreshAuth struct {
	LastAuthenticatedAt               *time.Time `json:"last_authenticated_at"`
	StepUpRequiredForSensitiveActions bool       `json:"step_up_required_for_sensitive_actions"`
	StepUpRequiredInSeconds           int64      `json:"step_up_required_in_seconds"`
	AuthMethods                       []string   `json:"auth_methods"`
}

FreshAuth is a session's step-up state: when it last proved its user, and how long sensitive actions stay open without a step-up (0 once one is required).

type InviteRedemption

type InviteRedemption struct {
	GroupID string
	Persona iam.Persona
	Role    iam.Role
}

InviteRedemption is the group and role a redeemed invite link granted.

type IssuedSession

type IssuedSession struct {
	SessionID       string
	RefreshToken    string
	AccessToken     string
	AccessExpiresAt time.Time
}

IssuedSession is a freshly established refresh session plus its paired access token.

func (IssuedSession) TokenSet

func (s IssuedSession) TokenSet() iam.TokenSet

TokenSet is the wire shape of an IssuedSession.

type LinkedProvider added in v0.149.0

type LinkedProvider struct {
	Provider string    `json:"provider"`
	Email    *string   `json:"email"`
	LinkedAt time.Time `json:"linked_at"`
}

LinkedProvider is a sign-in provider linked to the account, with the email the provider reported.

type LoginChallengeInput

type LoginChallengeInput struct {
	UserID     string
	Challenge  string
	FactorID   string
	Code       string
	BackupCode bool
	UserAgent  string
	IP         string
}

LoginChallengeInput supplies the second proof; clients never supply AMR or first-factor provenance. Backup codes are independently stored recovery keys.

type LoginOutcome

type LoginOutcome struct {
	Recovery       *AccountRecoveryConfirmation
	Enrollment     *iam.TokenSet
	AllowedMethods []iam.TwoFactorMethod
	ReturnTo       string
	Created        bool
	Kind           LoginOutcomeKind
	UserID         string
	Reason         error
	Session        *IssuedSession
	Verification   *VerificationRequired
	Challenge      *TwoFactorChallenge
}

LoginOutcome is the result of a password login. Exactly one of Session, Verification and Challenge is set, per Kind; Reason is set for LoginRejected.

type LoginOutcomeKind

type LoginOutcomeKind string

LoginOutcomeKind is the closed set of ways a login attempt ends.

const (
	LoginProviderLinked LoginOutcomeKind = "provider_linked"
	LoginContactChanged LoginOutcomeKind = "contact_changed"
	// LoginSessionIssued: the caller is signed in; Session carries the tokens.
	LoginSessionIssued LoginOutcomeKind = "session_issued"
	// LoginVerificationRequired: the identifier still needs verifying; a fresh
	// code was just sent to Verification.Identifier over Verification.Channel.
	LoginVerificationRequired LoginOutcomeKind = "verification_required"
	// LoginTwoFactorRequired: the password verified; a second factor is now
	// pending (Challenge carries the issued challenge and the factor menu).
	LoginTwoFactorRequired LoginOutcomeKind = "2fa_required"
	// LoginTwoFAEnrollmentRequired: the password verified but the deployment
	// requires a second factor the user has not enrolled yet.
	LoginTwoFAEnrollmentRequired LoginOutcomeKind = "2fa_enrollment_required"
	// LoginRejected: no session; Reason says why (ErrInvalidCredentials,
	// ErrUserBanned, ErrPasswordResetRequired).
	LoginRejected LoginOutcomeKind = "rejected"
)
const LoginRecoveryRequired LoginOutcomeKind = "account_recovery_required"

type MFAContinuationRequiredError

type MFAContinuationRequiredError struct {
	UserID    string
	SessionID string
	Reason    error
}

MFAContinuationRequiredError identifies the already-validated refresh session that needs a first-factor continuation. It never authorizes an arbitrary user.

func (*MFAContinuationRequiredError) Error

func (*MFAContinuationRequiredError) Unwrap

func (e *MFAContinuationRequiredError) Unwrap() error

type MFAStatus

type MFAStatus struct {
	Enabled        bool
	Satisfied      bool
	AllowedMethods []iam.TwoFactorMethod
}

type PasswordLoginInput

type PasswordLoginInput struct {
	Identifier string
	Password   string
	UserAgent  string
	IP         string
}

PasswordLoginInput is a password login attempt. Identifier is an email (contains "@"), an E.164 phone ("+…") or a username.

type PasswordlessLoginInput

type PasswordlessLoginInput struct {
	Identifier string
	Code       string
	Token      string
	UserAgent  string
	IP         string
}

PasswordlessLoginInput selects either a typed code or a link token, never both, and supplies request metadata for the resulting authentication.

type PasswordlessStartRequest

type PasswordlessStartRequest struct {
	Identifier         string
	Mode               string
	ReturnTo           string
	PreferredLanguage  string
	AccountInviteToken string
}

type PasswordlessStartResult

type PasswordlessStartResult struct {
	Sent    bool
	Channel string
	Code    string
	LinkURL string
}

type PendingRegistration

type PendingRegistration struct {
	Email             string
	Username          string
	PasswordHash      string
	PreferredLanguage string
}

PendingRegistration represents an unverified registration

type ProfileInput

type ProfileInput struct {
	UserID          string
	ClaimsUsername  string // fallback when the row carries no username
	AuthTime        time.Time
	StepUpSatisfied bool     // the presented token is fresh enough for sensitive actions
	AuthMethods     []string // the presented token's authentication methods (amr)
	// ProviderSupportsStepUp reports which linked providers can re-authenticate.
	ProviderSupportsStepUp func(provider string) bool
}

ProfileInput is what the transport knows that the engine does not: the verified claims' username/auth-time/sensitivity and the deployment's provider registry.

type RegisterInput

type RegisterInput struct {
	Identifier         string
	Username           string
	Password           string
	PreferredLanguage  string
	AccountInviteToken string
	UserAgent          string
	IP                 string
}

RegisterInput is a native-user registration attempt: Identifier is an email or an E.164 phone; the account is password-backed.

type RegisterOutcome

type RegisterOutcome struct {
	Login    *LoginOutcome
	Kind     RegisterOutcomeKind
	Username string
	Email    *string
	Phone    *string
}

RegisterOutcome reports who was registered and what happens next.

type RegisterOutcomeKind

type RegisterOutcomeKind string

RegisterOutcomeKind is the closed set of ways a registration ends.

const (
	// RegisterSignedIn: the account exists; Login is its first sign-in (a
	// session, or the step it waits on).
	RegisterSignedIn RegisterOutcomeKind = "signed_in"
	// RegisterVerifyEmail / RegisterVerifyPhone: the registration is pending
	// until the code just sent to the identifier is confirmed.
	RegisterVerifyEmail RegisterOutcomeKind = "verify_email"
	RegisterVerifyPhone RegisterOutcomeKind = "verify_phone"
)

type RemovedMFARoleAssignment

type RemovedMFARoleAssignment struct {
	PermissionGroupID string
	Persona           iam.Persona
	Role              iam.Role
	RemovedAt         time.Time
}

type SessionFreshness

type SessionFreshness struct {
	LastAuthenticatedAt           time.Time
	TimeUntilStepUpRequired       time.Duration
	StepUpRequiredForSensitiveOps bool
	AuthMethods                   []string
	// MFAAuthenticatedAt is when the session last proved a second factor.
	MFAAuthenticatedAt time.Time
}

func (SessionFreshness) AssuranceClaims

func (f SessionFreshness) AssuranceClaims(secondFactor bool) (authTime int64, amr []string, acr string)

AssuranceClaims are the token's auth_time, amr and acr. A token claims otp/mfa only as of the session's last MFA proof. For an account with a second factor (secondFactor), auth_time is that proof, so a password re-auth never makes it fresh, and a session that never proved it claims no MFA. For an account without one (passkeys only), a later re-auth without MFA is fresh but no longer MFA (P5).

type SessionRevokeReason

type SessionRevokeReason string

SessionRevokeReason identifies why a session (or set of sessions) was revoked.

const (
	SessionRevokeReasonLogout               SessionRevokeReason = "logout"
	SessionRevokeReasonUserRevoke           SessionRevokeReason = "user_revoke"
	SessionRevokeReasonUserRevokeAll        SessionRevokeReason = "user_revoke_all"
	SessionRevokeReasonAdminRevoke          SessionRevokeReason = "admin_revoke"
	SessionRevokeReasonAdminRevokeAll       SessionRevokeReason = "admin_revoke_all"
	SessionRevokeReasonPasswordChange       SessionRevokeReason = "password_change"
	SessionRevokeReasonAdminSetPassword     SessionRevokeReason = "admin_set_password"
	SessionRevokeReasonContactChange        SessionRevokeReason = "contact_change"
	SessionRevokeReasonContactProven        SessionRevokeReason = "contact_proven"
	SessionRevokeReasonMFAReset             SessionRevokeReason = "mfa_reset"
	SessionRevokeReasonBanned               SessionRevokeReason = "banned"
	SessionRevokeReasonSoftDeleted          SessionRevokeReason = "soft_deleted"
	SessionRevokeReasonEvicted              SessionRevokeReason = "evicted"
	SessionRevokeReasonRefreshReuseDetected SessionRevokeReason = "refresh_reuse_detected"
)

type SolanaLinkedAccount

type SolanaLinkedAccount struct {
	Provider            string     `json:"provider"`
	Issuer              string     `json:"issuer"`
	Address             string     `json:"address"`
	Verified            bool       `json:"verified"`
	VerifiedAt          *time.Time `json:"verified_at"`
	PrimarySNSName      *string    `json:"primary_sns_name"`
	SNSResolutionStatus string     `json:"sns_resolution_status"`
	SNSResolvedAt       *time.Time `json:"sns_resolved_at"`
	SNSStale            bool       `json:"sns_stale"`
	SNSError            *string    `json:"sns_error"`
}

SolanaLinkedAccount is the AuthKit-owned normalized metadata for a SIWS-linked wallet.

type StepUpRequired added in v0.149.0

type StepUpRequired struct {
	StepUpMethods []string                `json:"step_up_methods"`
	MaxAgeSeconds int64                   `json:"max_age_seconds"`
	StepUp2FA     *StepUpTwoFactorOptions `json:"step_up_2fa"`
	MFARequired   bool                    `json:"mfa_required"`
}

StepUpRequired is step_up_required's metadata: how the account can step up, the freshness window, and its second factors (MFARequired: a password alone never clears the gate).

type StepUpTwoFactorOption

type StepUpTwoFactorOption struct {
	Method      string  `json:"method"`
	IsDefault   bool    `json:"is_default"`
	Destination *string `json:"destination"`
}

StepUpTwoFactorOption is one second factor; Destination is the masked address its codes go to (null for an authenticator app).

type StepUpTwoFactorOptions

type StepUpTwoFactorOptions struct {
	Methods       []string                `json:"methods"`
	DefaultMethod string                  `json:"default_method"`
	Options       []StepUpTwoFactorOption `json:"options"`
}

StepUpTwoFactorOptions lists the second factors a step-up can use.

func NewStepUpTwoFactorOptions

func NewStepUpTwoFactorOptions(settings *TwoFactorSettings) *StepUpTwoFactorOptions

NewStepUpTwoFactorOptions lists the second factors a step-up can use, with the code destination masked. Nil when 2FA is not enabled.

type TwoFactorChallenge

type TwoFactorChallenge struct {
	Method      string
	Destination string // where the code went (email/phone), unmasked
	Challenge   string
	Factor      TwoFactorFactor
	Factors     []TwoFactorFactor
}

TwoFactorChallenge is the second-factor step a password login opened.

type TwoFactorEnrollInput

type TwoFactorEnrollInput struct {
	LoginChallenge string
	// SessionID is the caller's session; a confirmed code marks it 2FA-verified.
	SessionID   string
	UserAgent   string
	IP          string
	UserID      string
	Mode        FactorEnrollmentMode
	Method      string // "email" | "sms" | "totp"
	Code        string // email/SMS setup code or TOTP code; empty starts the method's setup
	PhoneNumber string
	MakeDefault bool
}

TwoFactorEnrollInput is one enrollment request: a setup to start (no Code), or the factor its Code proves to add.

type TwoFactorEnrollKind

type TwoFactorEnrollKind string

TwoFactorEnrollKind is the closed set of enrollment results.

const (
	TwoFactorEnrollCodeSent    TwoFactorEnrollKind = "code_sent"    // email/SMS setup code delivered
	TwoFactorEnrollTOTPStarted TwoFactorEnrollKind = "totp_started" // secret + otpauth URI handed out
	TwoFactorEnrollEnabled     TwoFactorEnrollKind = "enabled"
)

type TwoFactorEnrollOutcome

type TwoFactorEnrollOutcome struct {
	Login           *LoginOutcome
	Kind            TwoFactorEnrollKind
	Method          string
	Destination     string
	Secret          string
	OTPAuthURI      string
	Factor          TwoFactorFactor
	BackupCodes     []string
	SessionVerified bool
}

TwoFactorEnrollOutcome carries the setup code's Destination for TwoFactorEnrollCodeSent, the TOTP material for TwoFactorEnrollTOTPStarted, and for TwoFactorEnrollEnabled the new Factor with the plaintext backup codes (shown once, the first factor's only). SessionVerified reports that the input session now holds 2FA assurance.

type TwoFactorEnrollmentScope

type TwoFactorEnrollmentScope struct {
	Mode       FactorEnrollmentMode
	HasFactors bool
}

TwoFactorEnrollmentScope is what an enrollment call may do: the factor slot policy and whether the account already holds a factor.

type TwoFactorFactor

type TwoFactorFactor struct {
	ID          string
	UserID      string
	Method      string
	PhoneNumber *string
	// Email is the address an email factor was proven for; its codes go
	// there, never to the account's current address.
	Email        *string
	TOTPSecret   []byte
	LastTOTPStep *int64
	IsDefault    bool
	Enabled      bool
	CreatedAt    time.Time
	UpdatedAt    time.Time
}

type TwoFactorSettings

type TwoFactorSettings struct {
	UserID       string
	Enabled      bool
	Method       string // "email", "sms", or "totp"
	PhoneNumber  *string
	TOTPSecret   []byte
	LastTOTPStep *int64
	BackupCodes  []string // Hashed backup codes
	Factors      []TwoFactorFactor
	CreatedAt    time.Time
	UpdatedAt    time.Time
}

type UserProfile

type UserProfile struct {
	iam.User
	RootRole     *iam.Role            `json:"root_role"`
	Entitlements []string             `json:"entitlements"`
	HasPassword  bool                 `json:"has_password"`
	Providers    []LinkedProvider     `json:"providers"`
	SolanaWallet *SolanaLinkedAccount `json:"solana_wallet"`
	Naming       naming.State         `json:"naming"`
}

UserProfile is the caller's own account as GET /me and PATCH /me answer it: the account (iam.User), its root role, entitlements, sign-in methods, Solana wallet and rename state.

type UserSecurity

type UserSecurity struct {
	FreshAuth
	StepUpMethods     []string                `json:"step_up_methods"`
	StepUp2FA         *StepUpTwoFactorOptions `json:"step_up_2fa"`
	MFAEnabled        bool                    `json:"mfa_enabled"`
	MFASatisfied      bool                    `json:"mfa_satisfied"`
	MFAAllowedMethods []iam.TwoFactorMethod   `json:"mfa_allowed_methods"`
}

UserSecurity is GET /me/security: the session's freshness, how the account can step up, and its MFA state.

type VerificationInput

type VerificationInput struct {
	Identifier string
	Code       string
	Token      string
	UserID     string
	SessionID  string
	UserAgent  string
	IP         string
}

VerificationInput completes a delivered code/link. UserID and SessionID are supplied only from an authenticated host principal for contact changes.

type VerificationRequired

type VerificationRequired struct {
	Identifier string
	Channel    string // "email" | "phone"
}

VerificationRequired names the contact channel a login is parked on.

Jump to

Keyboard shortcuts

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