Documentation
¶
Index ¶
- Constants
- Variables
- func AssistedRecoveryOwnerConfirmation(subject SubjectID, email string) string
- func IsMFARecoveryCode(code string) bool
- func MFATOTPStep(secret, code string, now time.Time) (int64, bool, error)
- func NewMFALoginID() (string, error)
- func NewMFARecoveryCode() (string, error)
- func NormalizeEmail(value string) (string, error)
- func PasswordResetNotificationContext(ctx context.Context, notification Notification) (context.Context, error)
- func PasswordResetScope(ctx context.Context) string
- func ValidateMFALoginPending(pending MFALoginPending, account Account, factor MFAFactorRecord, realm Realm, ...) error
- func WithEmailChangeScope(ctx context.Context, scope EmailChangeScope) context.Context
- func WithPasswordResetScope(ctx context.Context, scope string) (context.Context, error)
- type Account
- type AccountStore
- type Argon2idConfig
- type Argon2idHasher
- type AssistedRecovery
- func (s *AssistedRecovery) Complete(ctx context.Context, request AssistedRecoveryCompletion) error
- func (s *AssistedRecovery) Initiate(ctx context.Context, request AssistedRecoveryRequest) error
- func (s *AssistedRecovery) InitiateOwner(ctx context.Context, request AssistedRecoveryOwnerRequest, ...) error
- type AssistedRecoveryAuthorization
- type AssistedRecoveryCompletion
- type AssistedRecoveryOwnerAuthorization
- type AssistedRecoveryOwnerRequest
- type AssistedRecoveryRecord
- type AssistedRecoveryRequest
- type AssistedRecoveryStore
- type AssistedRecoveryTarget
- type AssistedRecoveryTargetSnapshot
- type AuditSink
- type AuditSinkFunc
- type AuthContext
- type AuthTransaction
- type BasicProfile
- type ChangePasswordRequest
- type ClaimsEnricher
- type ClaimsEnricherFunc
- type CommonPasswordChecker
- type CommonPasswordCheckerFunc
- type Config
- type Credential
- type EmailChallengeIssueResult
- type EmailChallengeIssueStatus
- type EmailChallengeLimits
- type EmailChallengePurpose
- type EmailChallengeRecord
- type EmailChallengeStore
- type EmailChallengeVerifyRequest
- type EmailChallengeVerifyResult
- type EmailChallengeVerifyStatus
- type EmailChangeIssueResult
- type EmailChangeIssueStatus
- type EmailChangeRecord
- type EmailChangeScope
- type EmailChangeStore
- type EmailChangeTarget
- type EmailChangeTargetSnapshot
- type EmailChangeVerifyRequest
- type EmailChangeVerifyResult
- type EmailChangeVerifyStatus
- type EncryptedEnvelope
- type EncryptedEvent
- type EncryptedEventSink
- type ExternalIdentity
- type ExternalLoginRequest
- type Identifier
- type IdentifierInput
- type IdentifierResolver
- type IdentifierResolverFunc
- type IdentifierScheme
- type IdentityLink
- type IdentityLinkStore
- type ImportLocalIdentityRequest
- type Key
- type KeyRing
- type LocalAccountRecord
- type LocalCommonPasswordCheckerOption
- type LocalIdentifierReader
- type LocalIdentityRecord
- type LocalIdentityRenameStore
- type LocalIdentityRetirementStore
- type LocalIdentityStore
- type LocalIdentityView
- type LocalLoginResult
- type LoginRequest
- type LoginResult
- type MFAChangeRequest
- type MFAEnrollment
- type MFAEnrollmentConfirmRequest
- type MFAEnrollmentRecord
- type MFAEnrollmentRequest
- type MFAEnrollmentStore
- type MFAFactorCodec
- func (c *MFAFactorCodec) CheckKey(keyID string) error
- func (c *MFAFactorCodec) Open(subject SubjectID, factor, keyID string, ciphertext []byte) ([]byte, error)
- func (c *MFAFactorCodec) RecoveryDigest(subject SubjectID, factor, code string) ([]byte, error)
- func (c *MFAFactorCodec) Seal(subject SubjectID, factor, secret string) (string, []byte, error)
- type MFAFactorDecision
- type MFAFactorRecord
- type MFAFactorStore
- type MFALocalAdmissionStore
- type MFALoginChallenge
- type MFALoginKind
- type MFALoginPending
- type MFALoginSetup
- type MFAMode
- type MFARequiredStore
- type MFASessionAdmission
- type MFAStore
- type MembershipGate
- type MembershipGateFunc
- type Notification
- type NotificationDelivery
- type NotificationDeliveryPolicy
- type NotificationDiagnostic
- type NotificationDiagnosticError
- type NotificationRenderer
- type NotificationRendererFunc
- type NotificationSender
- type NotificationSenderFunc
- type NotificationTransactiondeprecated
- type PasswordChangeStoreRequest
- type PasswordChangeStoreResult
- type PasswordChangeStoreStatus
- type PasswordEmailChangeRequest
- type PasswordHasher
- type PasswordInputPolicy
- type PasswordPolicy
- type PasswordResetConsumeRequest
- type PasswordResetConsumeResult
- type PasswordResetConsumeStatus
- type PasswordResetReceipt
- type PasswordResetRecipientResolver
- type PasswordResetRecord
- type PasswordResetStore
- type PasswordResetSubjectStore
- type PendingEmailChange
- type PreparedPasswordChange
- type ProvisionLocalIdentityRequest
- type RateLimitPolicy
- type RateLimitRequest
- type RateLimitResult
- type RateLimitStore
- type Realm
- type RefreshRotationRequest
- type RefreshRotationResult
- type RefreshRotationStatus
- type RegisterRequest
- type RegisterResult
- type RenameLocalIdentityRequest
- type RenameLocalIdentityStoreRequest
- type RetireLocalIdentityRequest
- type RetireLocalIdentityStoreRequest
- type Runtime
- func (r *Runtime) AcknowledgeEncryptedEvent(ctx context.Context, eventID string) error
- func (r *Runtime) AuthenticateSession(ctx context.Context, token string) (AuthContext, error)
- func (r *Runtime) BeginLocalLogin(ctx context.Context, request LoginRequest, binding [32]byte) (LocalLoginResult, error)
- func (r *Runtime) BeginLocalLoginEnrollment(ctx context.Context, id string, binding [32]byte) (MFAEnrollment, error)
- func (r *Runtime) BeginMFAEnrollment(ctx context.Context, request MFAEnrollmentRequest) (MFAEnrollment, error)
- func (r *Runtime) CancelMFAEnrollment(ctx context.Context, auth AuthContext, binding [32]byte) error
- func (r *Runtime) ChangePassword(ctx context.Context, request ChangePasswordRequest) (Account, error)
- func (r *Runtime) CleanupExpiredEncryptedEvents(ctx context.Context) (int64, error)
- func (r *Runtime) CompleteLocalLogin(ctx context.Context, id string, binding [32]byte, code string) (LoginResult, error)
- func (r *Runtime) CompleteLocalLoginEnrollment(ctx context.Context, id, enrollmentID string, binding [32]byte, code string) (LoginResult, error)
- func (r *Runtime) CompletePasswordChange(ctx context.Context, subjectID SubjectID, proof *PreparedPasswordChange) (Account, error)
- func (r *Runtime) ConfirmEmailChange(ctx context.Context, subjectID SubjectID, code string) (Account, error)
- func (r *Runtime) ConfirmMFAEnrollment(ctx context.Context, request MFAEnrollmentConfirmRequest) ([]string, error)
- func (r *Runtime) DecryptNotificationEvent(event EncryptedEvent) (Notification, error)
- func (r *Runtime) DisableMFA(ctx context.Context, request MFAChangeRequest) error
- func (r *Runtime) FindAccount(ctx context.Context, identifier IdentifierInput) (Account, error)
- func (r *Runtime) GetAccount(ctx context.Context, subjectID SubjectID) (Account, error)
- func (r *Runtime) GetLocalIdentifier(ctx context.Context, subjectID SubjectID, scheme IdentifierScheme) (Identifier, error)
- func (r *Runtime) GetSubjectLifecycle(ctx context.Context, id SubjectID) (SubjectLifecycleView, error)
- func (r *Runtime) ImportLocalIdentity(ctx context.Context, request ImportLocalIdentityRequest) (Account, error)
- func (r *Runtime) LinkExternalIdentity(ctx context.Context, auth AuthContext, external ExternalIdentity) (IdentityLink, error)
- func (r *Runtime) Login(ctx context.Context, request LoginRequest) (LoginResult, error)
- func (r *Runtime) LoginExternal(ctx context.Context, request ExternalLoginRequest) (LoginResult, error)
- func (r *Runtime) Logout(ctx context.Context, subjectID SubjectID, sessionID string) error
- func (r *Runtime) LogoutAll(ctx context.Context, subjectID SubjectID) (int64, error)
- func (r *Runtime) MFAMode() MFAMode
- func (r *Runtime) MFAStatus(ctx context.Context, auth AuthContext) (bool, error)
- func (r *Runtime) PendingEmailChange(ctx context.Context, subjectID SubjectID) (PendingEmailChange, error)
- func (r *Runtime) PreparePasswordChange(ctx context.Context, request ChangePasswordRequest) (*PreparedPasswordChange, error)
- func (r *Runtime) PreparePasswordChangeWithIssuer(ctx context.Context, request ChangePasswordRequest, issuer *Runtime) (*PreparedPasswordChange, error)
- func (r *Runtime) ProvisionExternalIdentity(ctx context.Context, external ExternalIdentity) (Account, error)
- func (r *Runtime) ProvisionLocalIdentity(ctx context.Context, request ProvisionLocalIdentityRequest) (Account, error)
- func (r *Runtime) ProvisionTrustedLocalAccount(ctx context.Context, request RegisterRequest) (Account, error)
- func (r *Runtime) Refresh(ctx context.Context, rawRefreshToken string) (TokenPair, error)
- func (r *Runtime) RegenerateMFARecovery(ctx context.Context, request MFAChangeRequest) ([]string, error)
- func (r *Runtime) Register(ctx context.Context, request RegisterRequest) (RegisterResult, error)
- func (r *Runtime) RenameLocalIdentity(ctx context.Context, request RenameLocalIdentityRequest) (LocalIdentityView, error)
- func (r *Runtime) RequestEmailChange(ctx context.Context, subjectID SubjectID, newEmail string) error
- func (r *Runtime) RequestEmailChangeWithPassword(ctx context.Context, request PasswordEmailChangeRequest) error
- func (r *Runtime) RequestEmailChangeWithPreviousEmailNotice(ctx context.Context, subjectID SubjectID, newEmail, previousEmail string) error
- func (r *Runtime) RequestPasswordReset(ctx context.Context, email string) error
- func (r *Runtime) RequestPasswordResetWithReceipt(ctx context.Context, email string, ...) error
- func (r *Runtime) ResetPassword(ctx context.Context, rawToken, newPassword string) error
- func (r *Runtime) ResolveExternalIdentity(ctx context.Context, external ExternalIdentity) (Account, error)
- func (r *Runtime) RetireLocalIdentity(ctx context.Context, request RetireLocalIdentityRequest) (SubjectLifecycleView, error)
- func (r *Runtime) SendEmailChallenge(ctx context.Context, subjectID SubjectID, purpose EmailChallengePurpose) error
- func (r *Runtime) SetSubjectStatus(ctx context.Context, subjectID SubjectID, status SubjectStatus) (Subject, error)
- func (r *Runtime) SetTrustedLocalPassword(ctx context.Context, request SetTrustedLocalPasswordRequest) (Account, error)
- func (r *Runtime) UpdateBasicProfile(ctx context.Context, subjectID SubjectID, profile BasicProfile) (Account, error)
- func (r *Runtime) VerifyAccessToken(ctx context.Context, token string, introspect bool) (AuthContext, error)deprecated
- func (r *Runtime) VerifyCredential(ctx context.Context, credential Credential) (Account, error)
- func (r *Runtime) VerifyEmailChallenge(ctx context.Context, subjectID SubjectID, purpose EmailChallengePurpose, ...) (Account, error)
- func (r *Runtime) VerifyJWT(ctx context.Context, token string) (AuthContext, error)
- type RuntimeStore
- type SSOAccountRecord
- type ScopedEmailChangeStore
- type SecretDigest
- type SecurityEvent
- type SecurityEventType
- type Session
- type SessionRecord
- type SessionScope
- type SessionSecurity
- type SessionStore
- type SetTrustedLocalPasswordRequest
- type SigningConfig
- type Subject
- type SubjectID
- func (id SubjectID) IsZero() bool
- func (id SubjectID) MarshalText() ([]byte, error)
- func (id *SubjectID) Scan(source any) error
- func (id SubjectID) String() string
- func (id *SubjectID) UnmarshalText(value []byte) error
- func (id SubjectID) Validate() error
- func (id SubjectID) Value() (driver.Value, error)
- type SubjectLifecycleReader
- type SubjectLifecycleView
- type SubjectStatus
- type TokenPair
- type TrustedLocalPasswordStore
- type TrustedLocalPasswordStoreRequest
- type URLBuilder
- type URLBuilderFunc
Constants ¶
const ( DefaultPasswordMinLength = 8 DefaultPasswordMaxLength = 128 DefaultArgon2MemoryKiB = 19 * 1024 DefaultArgon2Iterations = 2 DefaultArgon2Parallelism = 1 DefaultMaxConcurrentPasswordHashes = 4 )
const AssistedRecoveryLifetime = 15 * time.Minute
const MFALoginLifetime = 3 * time.Minute
const (
MaxAccessTokenTTL = 5 * time.Minute
)
Variables ¶
var ( ErrAssistedRecoveryDenied = errors.New("assisted recovery denied") )
var ( ErrOperationOutcomeUnknown = errors.New("operation commit outcome is unknown") ErrInvalidSubjectID = errors.New("invalid subject ID") ErrInvalidSubjectStatus = errors.New("invalid subject status") ErrInvalidIdentifierScheme = errors.New("invalid identifier scheme") ErrInvalidIdentifier = errors.New("invalid identifier") ErrIdentifierAlreadyExists = errors.New("identifier already exists") ErrInvalidRealm = errors.New("invalid realm") ErrRealmNotRegistered = errors.New("realm is not registered") ErrInvalidChallengePurpose = errors.New("invalid email challenge purpose") ErrAccountNotFound = errors.New("account not found") ErrInvalidCredentials = errors.New("invalid credentials") ErrCurrentPasswordInvalid = errors.New("current password is invalid") ErrPasswordUnchanged = errors.New("new password matches current password") ErrPasswordChangeConflict = errors.New("password changed concurrently") ErrAuthenticationRateLimited = errors.New("authentication rate limited") ErrPasswordHashOverloaded = errors.New("password hashing capacity exhausted") ErrMembershipDenied = errors.New("realm membership denied") ErrEmailVerificationRequired = errors.New("verified email required") ErrInvalidPassword = errors.New("invalid password") ErrCommonPassword = errors.New("common password is not allowed") ErrInvalidToken = errors.New("invalid token") ErrReservedAccessTokenClaim = errors.New("claims enricher set a reserved access-token claim") ErrExpiredToken = errors.New("token expired") ErrRefreshReplay = errors.New("refresh token replay detected") ErrSessionRevoked = errors.New("session revoked") ErrSecurityVersionMismatch = errors.New("security version mismatch") ErrResetAlreadyUsed = errors.New("password reset token already used") ErrInvalidConfirmationCode = errors.New("invalid confirmation code") ErrConfirmationExpired = errors.New("confirmation code expired") ErrConfirmationAttempts = errors.New("confirmation attempts exhausted") ErrConfirmationRateLimited = errors.New("confirmation rate limited") ErrConfirmationResendDelay = errors.New("wait before resending confirmation") ErrEmailChangeNotFound = errors.New("pending email change not found") ErrEmailChangeSameValue = errors.New("new email matches current email") ErrKeyRingInvalid = errors.New("invalid key ring") ErrKeyPurposeCollision = errors.New("cryptographic key reused across purposes") ErrNotificationSinkRequired = errors.New("encrypted notification sink is required") ErrURLBuilderRequired = errors.New("URL builder is required") ErrIdentityLinkNotFound = errors.New("identity link not found") ErrIdentityLinkConflict = errors.New("identity link conflict") ErrExplicitIdentityLink = errors.New("explicit authenticated identity linking is required") )
var ( ErrLocalIdentifierUnsupported = errors.New("local identifier read capability is not supported") ErrLocalIdentityRenameUnsupported = errors.New("local identity rename capability is not supported") ErrLocalIdentifierConflict = errors.New("local primary identifier is missing or changed") ErrIdentifierUnchanged = errors.New("local identifier is unchanged") )
var ( ErrMFARequired = errors.New("second factor required") ErrMFALoginDenied = errors.New("MFA login denied") )
var ( ErrSubjectLifecycleUnsupported = errors.New("subject lifecycle read capability is not supported") ErrLocalIdentityRetirementUnsupported = errors.New("local identity retirement capability is not supported") ErrSubjectRetired = errors.New("authentication subject is permanently retired") )
var ErrLocalIdentityUnsupported = errors.New("local identity capability is not supported")
var ErrNotificationDeliveryDisabled = errors.New("notification delivery is disabled")
var ErrNotificationRejected = errors.New("notification permanently rejected")
ErrNotificationRejected is an explicit terminal non-delivery disposition from a NotificationSender. Return it, optionally wrapped, only when the transport has definitively rejected or simulated the operation without accepting real mail. Never use it for timeouts, lost responses or unknown provider outcomes. PostgreSQL records an unsuccessful terminal receipt (exhausted/sender_rejected), scrubs the envelope, and leaves delivered_at NULL. Ordinary errors keep retrying.
ErrPasswordVerificationUnavailable marks an operational failure from a custom PasswordHasher. Wrap or join the underlying cause to preserve diagnostics.
var ErrRateLimitTransactionUnsupported = errors.New("rate-limit admission requires no active auth transaction")
ErrRateLimitTransactionUnsupported means attempt admission was invoked inside a managed auth transaction. Call the rate-limited Runtime operation before opening an outer AuthTransaction; do not strip the callback context to retry. The built-in stores reject this composition before consuming an attempt or verifying a password. This is a wiring error, not a throttling or credential failure. Transactional email-issue quotas are not affected.
var ErrTrustedLocalPasswordUnsupported = errors.New("trusted local password capability is not supported")
var NilSubjectID = SubjectID(uuid.Nil)
Functions ¶
func AssistedRecoveryOwnerConfirmation ¶ added in v0.11.0
func IsMFARecoveryCode ¶ added in v0.8.0
func MFATOTPStep ¶ added in v0.8.0
MFATOTPStep uses six-digit SHA-1 TOTP, thirty-second periods and one-step skew. The store must atomically reject step <= the persisted LastStep.
func NewMFALoginID ¶ added in v0.8.0
func NewMFARecoveryCode ¶ added in v0.8.0
func NormalizeEmail ¶
func PasswordResetNotificationContext ¶ added in v0.8.0
func PasswordResetNotificationContext(ctx context.Context, notification Notification) (context.Context, error)
PasswordResetNotificationContext restores only the authenticated notification scope. Use it after DecryptNotificationEvent, never on untrusted input. Missing metadata explicitly restores the legacy empty scope instead of inheriting a worker's ambient scope. Malformed metadata fails closed.
func PasswordResetScope ¶ added in v0.8.0
PasswordResetScope returns the trusted scope of the current recovery operation. Recipient policies must reject scopes they do not explicitly support.
func ValidateMFALoginPending ¶ added in v0.8.0
func ValidateMFALoginPending(pending MFALoginPending, account Account, factor MFAFactorRecord, realm Realm, binding [32]byte, now time.Time, ) error
ValidateMFALoginPending validates a locked snapshot; it does not consume it. Sample now after waiting for locks, then independently check realm membership.
func WithEmailChangeScope ¶ added in v0.8.0
func WithEmailChangeScope(ctx context.Context, scope EmailChangeScope) context.Context
WithEmailChangeScope selects a configured host projection for the existing email-change APIs. An unknown nonempty scope fails closed.
func WithPasswordResetScope ¶ added in v0.8.0
WithPasswordResetScope binds a host-selected recovery authority to an operation. Callers must select scope from trusted route/configuration, never request fields. Empty scope preserves the legacy unscoped token purpose. A scoped token cannot be consumed in another scope, including the legacy empty scope.
Types ¶
type Account ¶
type Account struct {
Subject Subject
// PrimaryEmail is zero for deliberately provisioned email-less identities.
PrimaryEmail Identifier
Profile BasicProfile
}
func (Account) EmailVerified ¶
type AccountStore ¶
type AccountStore interface {
// LockAccount requires AuthTransaction and locks the canonical subject before dependent state.
LockAccount(ctx context.Context, subjectID SubjectID) (Account, error)
CreateLocalAccount(ctx context.Context, record LocalAccountRecord) (Account, error)
FindAccount(ctx context.Context, identifier IdentifierInput) (Account, error)
FindLocalAccount(ctx context.Context, identifier IdentifierInput) (LocalAccountRecord, error)
GetLocalAccount(ctx context.Context, subjectID SubjectID) (LocalAccountRecord, error)
GetAccount(ctx context.Context, subjectID SubjectID) (Account, error)
UpdateBasicProfile(ctx context.Context, subjectID SubjectID, profile BasicProfile, now time.Time) (Account, error)
ChangePassword(ctx context.Context, request PasswordChangeStoreRequest) (PasswordChangeStoreResult, error)
}
type Argon2idConfig ¶
type Argon2idHasher ¶
type Argon2idHasher struct {
// contains filtered or unexported fields
}
func NewArgon2idHasher ¶
func NewArgon2idHasher(config Argon2idConfig) (*Argon2idHasher, error)
func (*Argon2idHasher) HashPassword ¶
func (h *Argon2idHasher) HashPassword(password string) (string, error)
func (*Argon2idHasher) VerifyPassword ¶
func (h *Argon2idHasher) VerifyPassword(phc, password string) error
type AssistedRecovery ¶ added in v0.11.0
type AssistedRecovery struct {
// contains filtered or unexported fields
}
AssistedRecovery is a transport-neutral, explicitly configured host service. Hosts must expose initiation only to authenticated administrators with CSRF protection and must never log request secrets or invitation URLs.
func NewAssistedRecovery ¶ added in v0.11.0
func NewAssistedRecovery( runtime *Runtime, authorization AssistedRecoveryAuthorization, completionURL string, ) (*AssistedRecovery, error)
func NewScopedAssistedRecovery ¶ added in v0.11.0
func NewScopedAssistedRecovery( runtime *Runtime, authorization AssistedRecoveryAuthorization, completionURL, scope string, target AssistedRecoveryTarget, ) (*AssistedRecovery, error)
NewScopedAssistedRecovery handles a host projection with distinct MFA and issuance policy. Scope and target are trusted assembly configuration.
func (*AssistedRecovery) Complete ¶ added in v0.11.0
func (s *AssistedRecovery) Complete(ctx context.Context, request AssistedRecoveryCompletion) error
func (*AssistedRecovery) Initiate ¶ added in v0.11.0
func (s *AssistedRecovery) Initiate(ctx context.Context, request AssistedRecoveryRequest) error
func (*AssistedRecovery) InitiateOwner ¶ added in v0.11.0
func (s *AssistedRecovery) InitiateOwner( ctx context.Context, request AssistedRecoveryOwnerRequest, authorization AssistedRecoveryOwnerAuthorization, ) error
type AssistedRecoveryAuthorization ¶ added in v0.11.0
type AssistedRecoveryAuthorization interface {
AuthorizeAssistedRecovery(ctx context.Context, auth AuthContext, subject SubjectID, reason, reference string) error
}
AssistedRecoveryAuthorization is evaluated inside the security transaction. The host must check its dedicated recovery permission and independently verified identity evidence. A name or possession of the new email is not identity evidence. Neither this interface nor Auth may come from request JSON.
type AssistedRecoveryCompletion ¶ added in v0.11.0
type AssistedRecoveryOwnerAuthorization ¶ added in v0.11.0
type AssistedRecoveryOwnerAuthorization interface {
AuthorizeOwnerAssistedRecovery(ctx context.Context, subject SubjectID) error
}
AssistedRecoveryOwnerAuthorization is server-CLI authority only. Implementations must lock the owner population and verify this is the sole active owner. Never expose this capability through an HTTP route.
type AssistedRecoveryOwnerRequest ¶ added in v0.11.0
type AssistedRecoveryRecord ¶ added in v0.11.0
type AssistedRecoveryRecord struct {
OwnerCLI bool
Scope string
TargetVersion int64
Selector string
SubjectID SubjectID
ActorID SubjectID
Digest SecretDigest
SecurityVersion int64
OldEmail string
NewEmail string
CreatedAt time.Time
ExpiresAt time.Time
}
AssistedRecoveryRecord contains only a keyed token digest. Stores must join AuthTransaction, lock subject before record, and bind the invitation to the exact security version and current primary email. Later issuance supersedes earlier invitations without modifying account security state.
type AssistedRecoveryRequest ¶ added in v0.11.0
type AssistedRecoveryRequest struct {
Auth AuthContext
SubjectID SubjectID
NewEmail string
Password string
Code string
Reason string
EvidenceReference string
}
AssistedRecoveryRequest identifies an existing local account. Starting a recovery never changes its email, password, MFA, roles, or sessions.
type AssistedRecoveryStore ¶ added in v0.11.0
type AssistedRecoveryStore interface {
CreateAssistedRecovery(ctx context.Context, record AssistedRecoveryRecord) error
FindAssistedRecoverySubject(ctx context.Context, selector string) (SubjectID, error)
LockAssistedRecovery(ctx context.Context, selector string) (AssistedRecoveryRecord, error)
// CompleteAssistedRecovery performs exact-record CAS, preserves identity and
// roles, changes email and password together, advances security version, and
// invalidates all sessions, refresh families and recovery links atomically.
CompleteAssistedRecovery(
ctx context.Context, record AssistedRecoveryRecord, passwordPHC string, now time.Time,
) (Account, error)
}
type AssistedRecoveryTarget ¶ added in v0.11.0
type AssistedRecoveryTarget interface {
ReadAssistedRecoveryTarget(ctx context.Context, subject SubjectID) (AssistedRecoveryTargetSnapshot, error)
ReplaceAssistedRecoveryTarget(
ctx context.Context, subject SubjectID, snapshot AssistedRecoveryTargetSnapshot, email string, now time.Time,
) error
VerifyAssistedRecoveryFactor(ctx context.Context, subject SubjectID, code string, now time.Time) (bool, error)
PrepareAssistedRecoveryPassword(ctx context.Context, subject SubjectID, password string) (string, error)
}
AssistedRecoveryTarget is a host-owned email projection on this exact auth database. Every method joins the managed transaction. Read must lock its target; Replace must use email/version CAS and invalidate host sessions. VerifyFactor must preserve enrollment and durably charge incorrect attempts. PreparePassword must apply the host's existing issuance policy and hash budget.
type AssistedRecoveryTargetSnapshot ¶ added in v0.11.0
type AuditSink ¶
type AuditSink interface {
RecordSecurityEvent(ctx context.Context, event SecurityEvent) error
}
type AuditSinkFunc ¶
type AuditSinkFunc func(context.Context, SecurityEvent) error
func (AuditSinkFunc) RecordSecurityEvent ¶
func (f AuditSinkFunc) RecordSecurityEvent(ctx context.Context, event SecurityEvent) error
type AuthContext ¶
type AuthTransaction ¶ added in v0.5.0
type AuthTransaction interface {
InAuthTransaction(ctx context.Context, fn func(context.Context) error) error
}
AuthTransaction atomically commits all participating auth, audit and encrypted event writes. Callback errors roll back. A failed commit with uncertain server outcome must wrap ErrOperationOutcomeUnknown. Nested auth writes join the same scope. Credential-attempt admission is separate: built-in stores reject TakeRateLimit in this scope with ErrRateLimitTransactionUnsupported. Call rate-limited Runtime operations outside an outer transaction. Hooks must not perform irreversible external actions inside this callback.
type BasicProfile ¶
type ChangePasswordRequest ¶
type ClaimsEnricher ¶
type ClaimsEnricherFunc ¶
func (ClaimsEnricherFunc) EnrichClaims ¶
type CommonPasswordChecker ¶
func NewLocalCommonPasswordChecker ¶ added in v0.7.0
func NewLocalCommonPasswordChecker( passwords []string, options ...LocalCommonPasswordCheckerOption, ) (CommonPasswordChecker, error)
NewLocalCommonPasswordChecker copies passwords into an immutable in-memory dictionary implementing CommonPasswordChecker. It is safe for concurrent reads after construction; callers must not mutate passwords during construction.
Entries and queries use strings.ToLower(strings.TrimSpace(value)), matching the built-in checker. There is no Unicode normalization or full case folding. Invalid UTF-8 entries, entries empty after trimming, and nil options return a nil checker and an error that never contains the entry text. Duplicates are accepted. Invalid UTF-8 queries never match.
A nil or empty passwords slice is valid and blocks nothing unless WithBuiltInCommonPasswords is supplied. Assigning the result to PasswordPolicy.Blocklist replaces that policy's checker; built-ins are not included implicitly. Construction does not change any existing policy. Checks are synchronous and perform no I/O; the existing bool-only interface has no context or operational-error contract.
type CommonPasswordCheckerFunc ¶
func (CommonPasswordCheckerFunc) IsCommonPassword ¶
func (f CommonPasswordCheckerFunc) IsCommonPassword(password string) bool
type Config ¶
type Config struct {
// EmailChangeTargets registers explicitly scoped host-owned address projections.
EmailChangeTargets map[EmailChangeScope]EmailChangeTarget
// MFAKeys enables optional local-factor verification. Nil never bypasses stored enrollment.
MFAKeys *KeyRing
MFAMode MFAMode
NotificationDelivery NotificationDeliveryPolicy
Store RuntimeStore
Signing SigningConfig
TokenHMACKeys KeyRing
OutboxAEADKeys KeyRing
EventSink EncryptedEventSink
NotificationTransaction NotificationTransaction // Deprecated: use AuthTransaction.
AuthTransaction AuthTransaction
// Nil allows all trusted issuers; empty disables verified-email auto-linking.
AutoLinkVerifiedEmailIssuers []string
// ManagedNotificationDelivery enables typed, lease-owned PostgreSQL delivery.
// A custom transaction alone keeps the configured renderer and event sink.
ManagedNotificationDelivery bool
IdentifierResolvers map[IdentifierScheme]IdentifierResolver
MembershipGate MembershipGate
ClaimsEnricher ClaimsEnricher
NotificationRenderer NotificationRenderer
URLBuilder URLBuilder
AuditSink AuditSink
PasswordHasher PasswordHasher
// EnableLegacyBytes256 opts into two sequential, equal-profile verification jobs.
// Requires the built-in hasher and a profile preflight; see docs/local-identities.md.
EnableLegacyBytes256 bool
// Zero defaults to four concurrent hashes/verifications per shared Runtime.
// Excess work fails immediately with ErrPasswordHashOverloaded.
MaxConcurrentPasswordHashes int
PasswordPolicy PasswordPolicy
AdditionalRealms []Realm
AccessTTL time.Duration
SessionTTL time.Duration
RefreshTTL time.Duration
PasswordResetTTL time.Duration
ChallengeTTL time.Duration
EmailChangeTTL time.Duration
EnvelopeRetention time.Duration
ResetResponseFloor time.Duration
IdentityLinkAuthMaxAge time.Duration
LoginRateLimit RateLimitPolicy
// CredentialVerificationRateLimit bounds VerifyCredential and PostgreSQL
// PrepareCredential separately from browser login. Zero inherits LoginRateLimit.
// Every verification attempt, including success, still consumes admission.
CredentialVerificationRateLimit RateLimitPolicy
// PasswordResetRecipientResolver opts into host-authorized recovery addresses.
// Nil retains primary-email-only recovery. See docs/password-reset-recipients.md.
PasswordResetRecipientResolver PasswordResetRecipientResolver
PasswordResetRateLimit RateLimitPolicy
Now func() time.Time
Random io.Reader
}
type Credential ¶
type Credential struct {
Identifier IdentifierInput
Password string
}
type EmailChallengeIssueResult ¶
type EmailChallengeIssueResult struct {
Status EmailChallengeIssueStatus
RetryAt time.Time
}
type EmailChallengeIssueStatus ¶
type EmailChallengeIssueStatus string
const ( EmailChallengeIssued EmailChallengeIssueStatus = "issued" EmailChallengeWait EmailChallengeIssueStatus = "wait" EmailChallengeHourlyLimit EmailChallengeIssueStatus = "hourly_limit" EmailChallengeDailyLimit EmailChallengeIssueStatus = "daily_limit" )
type EmailChallengeLimits ¶
type EmailChallengePurpose ¶
type EmailChallengePurpose string
const EmailChallengePurposeVerification EmailChallengePurpose = "verification"
func (EmailChallengePurpose) Validate ¶
func (p EmailChallengePurpose) Validate() error
type EmailChallengeRecord ¶
type EmailChallengeRecord struct {
ID string
SubjectID SubjectID
IdentifierID string
// Runtime supplies these together so a store can reject a challenge if
// the account changes after the caller reads its email destination.
ExpectedNormalizedEmail string
ExpectedSecurityVersion int64
Purpose EmailChallengePurpose
Digest SecretDigest
RateDigest SecretDigest
MaxAttempts int
ExpiresAt time.Time
CreatedAt time.Time
}
type EmailChallengeStore ¶
type EmailChallengeStore interface {
IssueEmailChallenge(
ctx context.Context,
record EmailChallengeRecord,
limits EmailChallengeLimits,
) (EmailChallengeIssueResult, error)
VerifyEmailChallenge(ctx context.Context, request EmailChallengeVerifyRequest) (EmailChallengeVerifyResult, error)
}
type EmailChallengeVerifyRequest ¶
type EmailChallengeVerifyRequest struct {
SubjectID SubjectID
Purpose EmailChallengePurpose
Digests []SecretDigest
Now time.Time
}
type EmailChallengeVerifyResult ¶
type EmailChallengeVerifyResult struct {
Status EmailChallengeVerifyStatus
Account Account
Attempts int
}
type EmailChallengeVerifyStatus ¶
type EmailChallengeVerifyStatus string
const ( EmailChallengeVerified EmailChallengeVerifyStatus = "verified" EmailChallengeInvalid EmailChallengeVerifyStatus = "invalid" EmailChallengeExpired EmailChallengeVerifyStatus = "expired" EmailChallengeAttemptsUsed EmailChallengeVerifyStatus = "attempts_used" EmailChallengeAlreadyVerified EmailChallengeVerifyStatus = "already_verified" )
type EmailChangeIssueResult ¶
type EmailChangeIssueResult struct {
Status EmailChangeIssueStatus
RetryAt time.Time
}
type EmailChangeIssueStatus ¶
type EmailChangeIssueStatus string
const ( EmailChangeIssued EmailChangeIssueStatus = "issued" EmailChangeWait EmailChangeIssueStatus = "wait" EmailChangeHourlyLimit EmailChangeIssueStatus = "hourly_limit" EmailChangeDailyLimit EmailChangeIssueStatus = "daily_limit" EmailChangeSameValue EmailChangeIssueStatus = "same_value" )
type EmailChangeRecord ¶
type EmailChangeRecord struct {
Scope EmailChangeScope
ExpectedSecurityVersion int64
TargetSnapshot EmailChangeTargetSnapshot
ID string
SubjectID SubjectID
NewDisplayValue string
NewNormalizedValue string
Digest SecretDigest
RateDigest SecretDigest
MaxAttempts int
ExpiresAt time.Time
CreatedAt time.Time
}
type EmailChangeScope ¶ added in v0.8.0
type EmailChangeScope string
EmailChangeScope identifies a host-owned recovery-address projection. The empty scope retains the primary-email contract. A scope is trusted host authority and must never be selected from an untrusted form or URL.
func EmailChangeScopeFromContext ¶ added in v0.8.0
func EmailChangeScopeFromContext(ctx context.Context) EmailChangeScope
type EmailChangeStore ¶
type EmailChangeStore interface {
IssueEmailChange(
ctx context.Context,
record EmailChangeRecord,
limits EmailChallengeLimits,
) (EmailChangeIssueResult, error)
GetPendingEmailChange(ctx context.Context, subjectID SubjectID, now time.Time) (PendingEmailChange, error)
VerifyEmailChange(ctx context.Context, request EmailChangeVerifyRequest) (EmailChangeVerifyResult, error)
}
type EmailChangeTarget ¶ added in v0.8.0
type EmailChangeTarget interface {
SnapshotEmailChangeTarget(ctx context.Context, subject SubjectID) (EmailChangeTargetSnapshot, error)
ApplyVerifiedEmailChange(ctx context.Context, subject SubjectID,
expected EmailChangeTargetSnapshot, newEmail string, now time.Time) error
}
EmailChangeTarget must join the Runtime's auth transaction. Snapshot is read under the canonical subject lock. Apply must CAS the complete old snapshot, write only this projection, and invalidate dependent host security state. It must not mutate the subject, primary email, credentials, or issue sessions.
type EmailChangeTargetSnapshot ¶ added in v0.8.0
EmailChangeTargetSnapshot is a versioned host-owned address. An absent address may be empty, but its version must remain positive and monotonic.
type EmailChangeVerifyRequest ¶
type EmailChangeVerifyRequest struct {
Scope EmailChangeScope
RecordID string
ExpectedSecurityVersion int64
SubjectID SubjectID
Digests []SecretDigest
Now time.Time
}
type EmailChangeVerifyResult ¶
type EmailChangeVerifyResult struct {
Status EmailChangeVerifyStatus
Account Account
Attempts int
}
type EmailChangeVerifyStatus ¶
type EmailChangeVerifyStatus string
const ( EmailChangeVerified EmailChangeVerifyStatus = "verified" EmailChangeInvalid EmailChangeVerifyStatus = "invalid" EmailChangeExpired EmailChangeVerifyStatus = "expired" EmailChangeAttemptsUsed EmailChangeVerifyStatus = "attempts_used" EmailChangeNotFound EmailChangeVerifyStatus = "not_found" )
type EncryptedEnvelope ¶
type EncryptedEvent ¶
type EncryptedEventSink ¶
type ExternalIdentity ¶
type ExternalIdentity struct {
Issuer string
Subject string
Email string
EmailVerified bool
Profile BasicProfile
}
type ExternalLoginRequest ¶
type ExternalLoginRequest struct {
Identity ExternalIdentity
Realm Realm
}
type Identifier ¶
type Identifier struct {
ID string
SubjectID SubjectID
Scheme IdentifierScheme
DisplayValue string
NormalizedValue string
VerifiedAt *time.Time
CreatedAt time.Time
UpdatedAt time.Time
}
Identifier stores both a display value and its scheme-specific canonical value. VerifiedAt is the only source for verification claims.
func (Identifier) IsVerified ¶
func (i Identifier) IsVerified() bool
type IdentifierInput ¶
type IdentifierInput struct {
Scheme IdentifierScheme
Value string
}
type IdentifierResolver ¶
type IdentifierResolver interface {
NormalizeIdentifier(ctx context.Context, input IdentifierInput) (IdentifierInput, error)
}
type IdentifierResolverFunc ¶
type IdentifierResolverFunc func(context.Context, IdentifierInput) (IdentifierInput, error)
func (IdentifierResolverFunc) NormalizeIdentifier ¶
func (f IdentifierResolverFunc) NormalizeIdentifier(ctx context.Context, input IdentifierInput) (IdentifierInput, error)
type IdentifierScheme ¶
type IdentifierScheme string
const IdentifierSchemeEmail IdentifierScheme = "email"
func (IdentifierScheme) Validate ¶
func (s IdentifierScheme) Validate() error
type IdentityLink ¶
type IdentityLinkStore ¶
type IdentityLinkStore interface {
ResolveIdentityLink(ctx context.Context, issuer, externalSubject string) (Account, IdentityLink, error)
CreateSSOAccount(ctx context.Context, record SSOAccountRecord) (Account, IdentityLink, error)
LinkIdentity(ctx context.Context, link IdentityLink) (IdentityLink, error)
}
type ImportLocalIdentityRequest ¶ added in v0.6.0
type ImportLocalIdentityRequest struct {
SubjectID SubjectID
Identifier IdentifierInput
PasswordPHC string
PasswordInputPolicy PasswordInputPolicy
Profile BasicProfile
Status SubjectStatus
}
ImportLocalIdentityRequest imports one existing email-less local identity. SubjectID is assigned by the host's durable migration mapping. Status must be explicit. PHCs must be canonical and match the configured current profile, or the fixed legacy profile when EnableLegacyBytes256 is enabled.
type KeyRing ¶
type KeyRing struct {
// contains filtered or unexported fields
}
KeyRing is an immutable versioned set of 256-bit symmetric keys.
func (KeyRing) ActiveKeyID ¶
type LocalAccountRecord ¶
type LocalAccountRecord struct {
Account Account
PasswordPHC string
PasswordInputPolicy PasswordInputPolicy
}
type LocalCommonPasswordCheckerOption ¶ added in v0.7.0
type LocalCommonPasswordCheckerOption func(*localCommonPasswordCheckerConfig)
LocalCommonPasswordCheckerOption configures NewLocalCommonPasswordChecker. Use WithBuiltInCommonPasswords to include the default dictionary.
func WithBuiltInCommonPasswords ¶ added in v0.7.0
func WithBuiltInCommonPasswords() LocalCommonPasswordCheckerOption
WithBuiltInCommonPasswords adds the existing built-in dictionary to a local checker. It does not modify the default dictionary or any other checker. Repeating this option has the same effect as supplying it once.
type LocalIdentifierReader ¶ added in v0.6.0
type LocalIdentifierReader interface {
GetLocalIdentifier(ctx context.Context, subjectID SubjectID, scheme IdentifierScheme) (Identifier, error)
}
LocalIdentifierReader is an optional read-only RuntimeStore capability. Return only the subject's primary custom identifier for the explicit non-email scheme, never a secondary alias or credential. Missing rows return ErrLocalIdentifierConflict. Reads must join an existing AuthTransaction and reject foreign transaction scopes.
type LocalIdentityRecord ¶ added in v0.6.0
type LocalIdentityRecord struct {
LocalAccountRecord
Identifier Identifier
}
LocalIdentityRecord is a create-only, email-less account with one custom login identifier. The identifier is not an email or a verification assertion.
type LocalIdentityRenameStore ¶ added in v0.6.0
type LocalIdentityRenameStore interface {
RenameLocalIdentity(ctx context.Context, request RenameLocalIdentityStoreRequest) (LocalIdentityView, error)
}
LocalIdentityRenameStore is an optional capability; required store interfaces remain unchanged. Lock subject before its identifier and credential; require an existing credential, compare security version then old normalized identifier. Preserve status, identifier ID/creation time, profile, email, links and credential. A real edit advances security version exactly once and invalidates sessions, local/OIDC families, resets and pending email security state in AuthTransaction. Exact no-ops return ErrIdentifierUnchanged after CAS without any writes. Collisions (including same-subject aliases) return ErrIdentifierAlreadyExists, never merge. Overflow fails closed. The Runtime adds mandatory audit to the same transaction.
type LocalIdentityRetirementStore ¶ added in v0.6.0
type LocalIdentityRetirementStore interface {
RetireLocalIdentity(ctx context.Context, request RetireLocalIdentityStoreRequest) (SubjectLifecycleView, error)
}
LocalIdentityRetirementStore is an optional capability; required store interfaces remain unchanged. Lock subject first, reject retirement, then check version, exact primary custom login and existing local credential. Atomically mark disabled/retired, increment once (including ordinary-disabled subjects), delete ONLY the selected identifier and the local credential, revoke sessions, local/OIDC families, resets and pending email security state. Keep UUID, profile, audit, RBAC, every other identifier and external link. Overflow denies. Return persisted timestamps. The Runtime adds mandatory transactional audit.
Implementing this capability requires terminality across ALL store mutation paths: status/rename/password/credential/link writes cannot revive or attach authentication to a retired subject. Never clear the marker or reuse its ID. Retained bindings are deny-only, never reassigned or silently linked. Stores that cannot enforce these requirements must not advertise this capability.
type LocalIdentityStore ¶ added in v0.6.0
type LocalIdentityStore interface {
CreateLocalIdentity(ctx context.Context, record LocalIdentityRecord) (Account, error)
}
LocalIdentityStore is an optional capability for privileged local identities. Implementations must persist PasswordInputPolicy, return it on every credential read, and clear it to Unicode on password change/reset. Creates must reject any existing subject or identifier, never merge, and join AuthTransaction.
type LocalIdentityView ¶ added in v0.6.0
type LocalIdentityView struct {
Account Account
Identifier Identifier
}
LocalIdentityView is a safe identity read model, without credential material.
type LocalLoginResult ¶ added in v0.8.0
type LocalLoginResult struct {
Login LoginResult
Pending *MFALoginChallenge
}
type LoginRequest ¶
type LoginRequest struct {
Credential Credential
Realm Realm
}
type LoginResult ¶
type MFAChangeRequest ¶ added in v0.8.0
type MFAChangeRequest struct {
Auth AuthContext
Password string
Code string
}
type MFAEnrollment ¶ added in v0.8.0
type MFAEnrollmentConfirmRequest ¶ added in v0.8.0
type MFAEnrollmentConfirmRequest struct {
Auth AuthContext
Password string
EnrollmentID string
Code string
Binding [32]byte
}
type MFAEnrollmentRecord ¶ added in v0.8.0
type MFAEnrollmentRequest ¶ added in v0.8.0
type MFAEnrollmentRequest struct {
Auth AuthContext
Password string
CurrentCode string
Binding [32]byte
}
Auth must come from verified host authentication, never request JSON.
type MFAEnrollmentStore ¶ added in v0.8.0
type MFAEnrollmentStore interface {
EnsureMFAFactor(ctx context.Context, subject SubjectID) (MFAFactorRecord, error)
SaveMFAEnrollment(ctx context.Context, enrollment MFAEnrollmentRecord) error
LockMFAEnrollment(ctx context.Context, subject SubjectID) (MFAEnrollmentRecord, error)
ReplaceMFAFactor(ctx context.Context, subject SubjectID, previous, next MFAFactorRecord) (bool, error)
ReplaceMFARecovery(ctx context.Context, subject SubjectID, digests [][]byte) error
CancelMFAEnrollment(ctx context.Context, subject SubjectID, sessionID string, binding [32]byte) error
InvalidateMFAState(ctx context.Context, subject SubjectID) error
}
type MFAFactorCodec ¶ added in v0.8.0
type MFAFactorCodec struct {
// contains filtered or unexported fields
}
MFAFactorCodec retains an explicit persistent domain. Existing AuthHub rows use authhub/mfa; native local factors use goauth/mfa. Keep historical keys.
func NewMFAFactorCodec ¶ added in v0.8.0
func NewMFAFactorCodec(keys KeyRing, domain string) (*MFAFactorCodec, error)
func (*MFAFactorCodec) CheckKey ¶ added in v0.8.0
func (c *MFAFactorCodec) CheckKey(keyID string) error
func (*MFAFactorCodec) Open ¶ added in v0.8.0
func (c *MFAFactorCodec) Open(subject SubjectID, factor, keyID string, ciphertext []byte) ([]byte, error)
Open returns caller-owned secret bytes; clear them after use.
func (*MFAFactorCodec) RecoveryDigest ¶ added in v0.8.0
func (c *MFAFactorCodec) RecoveryDigest(subject SubjectID, factor, code string) ([]byte, error)
type MFAFactorDecision ¶ added in v0.8.0
type MFAFactorDecision uint8
const ( MFAFactorDenied MFAFactorDecision = iota MFAFactorVerified MFAFactorRateLimited )
func ConsumeMFAFactorLocked ¶ added in v0.8.0
func ConsumeMFAFactorLocked(ctx context.Context, store MFAFactorStore, codec *MFAFactorCodec, subject SubjectID, factor MFAFactorRecord, code string, now time.Time, ) (MFAFactorDecision, error)
ConsumeMFAFactorLocked is for adapters that already charged a durable attempt in this same transaction. Never use it without that admission.
func VerifyMFAFactorLocked ¶ added in v0.8.0
func VerifyMFAFactorLocked(ctx context.Context, store MFAFactorStore, codec *MFAFactorCodec, subject SubjectID, factor MFAFactorRecord, code string, now time.Time, ) (MFAFactorDecision, error)
VerifyMFAFactorLocked only consumes a factor; it is not a login proof. The caller validates the subject, session/challenge, binding, revision and expiry, and commits factor, challenge, session and audit together before publishing.
type MFAFactorRecord ¶ added in v0.8.0
type MFAFactorRecord struct {
ID string
Revision int64
Enabled bool
KeyID string
Ciphertext []byte
LastStep int64
}
MFAFactorRecord is durable encrypted state. Revision advances on every enrollment replacement, disable, or recovery-code regeneration.
type MFAFactorStore ¶ added in v0.8.0
type MFAFactorStore interface {
LockMFAFactor(ctx context.Context, subject SubjectID) (MFAFactorRecord, error)
TakeMFAAttempt(ctx context.Context, subject SubjectID) (bool, error)
ConsumeMFARecovery(ctx context.Context, subject SubjectID, factorID string, revision int64, digest []byte) (bool, error)
AdvanceMFAStep(ctx context.Context, subject SubjectID, factorID string, revision, previous, next int64) (bool, error)
}
MFAFactorStore joins a subject-locked auth transaction. Expected business denials commit their attempt budget. Consume operations must compare the exact enabled factor ID and revision and atomically consume the digest/step.
type MFALocalAdmissionStore ¶ added in v0.8.0
type MFALocalAdmissionStore interface {
LocalMFARequired(ctx context.Context, subject SubjectID) (bool, error)
}
MFALocalAdmissionStore must remain enabled even when MFA keys are absent. A legacy custom store may omit it only if it cannot contain enrolled factors.
type MFALoginChallenge ¶ added in v0.8.0
type MFALoginChallenge struct {
Kind MFALoginKind
ID string
ExpiresAt time.Time
}
type MFALoginKind ¶ added in v0.8.0
type MFALoginKind string
const ( MFALoginKindFactor MFALoginKind = "factor" MFALoginKindEnrollment MFALoginKind = "enrollment" )
type MFALoginPending ¶ added in v0.8.0
type MFALoginPending struct {
Kind MFALoginKind
Setup MFALoginSetup
ID string
SubjectID SubjectID
Realm Realm
SecurityVersion int64
FactorID string
FactorRevision int64
BindingDigest [32]byte
AuthenticatedAt time.Time
ExpiresAt time.Time
}
MFALoginPending is server-side continuation state, not authorization. ID is a random selector. BindingDigest hashes independent server browser state.
type MFALoginSetup ¶ added in v0.8.0
MFALoginSetup is encrypted setup material bound to one password-verified continuation. It has no lifetime independent of its parent pending record.
type MFAMode ¶ added in v0.8.0
type MFAMode string
MFAMode is trusted runtime configuration, never a browser-supplied login option.
type MFARequiredStore ¶ added in v0.8.0
type MFARequiredStore interface {
MFAStore
SaveMFALoginSetup(ctx context.Context, pending MFALoginPending, setup MFALoginSetup) error
MarkMFASessionAdmission(ctx context.Context, session Session, admission MFASessionAdmission) error
AdmitRequiredMFASession(ctx context.Context, session Session) error
}
MFARequiredStore extends the optional module without silently upgrading third-party stores that cannot enforce required enrollment and live admission.
type MFASessionAdmission ¶ added in v0.8.0
type MFASessionAdmission string
MFASessionAdmission is immutable server-written provenance. External admission is only written by LoginExternal after the host has verified that authority.
const ( MFASessionAdmissionFactor MFASessionAdmission = "factor" MFASessionAdmissionExternal MFASessionAdmission = "external" )
type MFAStore ¶ added in v0.8.0
type MFAStore interface {
MFAFactorStore
MFALocalAdmissionStore
MFAEnrollmentStore
FindMFALoginSubject(ctx context.Context, id string) (SubjectID, error)
CreateMFALogin(ctx context.Context, pending MFALoginPending) error
LockMFALogin(ctx context.Context, id string) (MFALoginPending, error)
ConsumeMFALogin(ctx context.Context, pending MFALoginPending) (bool, error)
}
MFAStore operations join the caller's transaction with subject, factor, then pending locks. Consumption is exact-record CAS, never a read followed by delete.
type MembershipGate ¶
type MembershipGateFunc ¶
func (MembershipGateFunc) AllowMembership ¶
type Notification ¶
type NotificationDelivery ¶
type NotificationDelivery struct {
ID string
// EncryptedEvent is the exact sealed event claimed by the managed worker.
// Delivery transports may persist this envelope, but never Notification's
// plaintext codes/tokens. Use ID for downstream idempotency; delivery is at-least-once.
EncryptedEvent EncryptedEvent
Notification Notification
ValidUntil time.Time
}
NotificationDelivery may be sent more than once before it is accepted, expires, or exhausts the attempt limit. A sender must use ID as its idempotency key when the underlying transport supports deduplication.
type NotificationDeliveryPolicy ¶ added in v0.5.0
type NotificationDeliveryPolicy uint8
NotificationDeliveryPolicy selects whether recovery and email commands are available. The zero value retains mandatory encrypted delivery.
const ( NotificationDeliveryRequired NotificationDeliveryPolicy = iota NotificationDeliveryDisabled )
type NotificationDiagnostic ¶ added in v0.10.0
NotificationDiagnostic is a bounded, transport-safe explanation of a sender failure. It must never contain an address, URL, response body, credential or raw error. PostgreSQL independently validates every tuple before persisting it. HTTPStatus is zero when no HTTP response was observed. This is an observation of one attempt, never proof of delivery or a change to retry policy.
type NotificationDiagnosticError ¶ added in v0.10.0
type NotificationDiagnosticError interface {
error
NotificationDiagnostic() NotificationDiagnostic
}
NotificationDiagnosticError optionally enriches a sender error. Existing NotificationSender implementations remain compatible. Wrapped errors are supported via errors.As; rejection still requires ErrNotificationRejected.
type NotificationRenderer ¶
type NotificationRenderer interface {
RenderNotification(ctx context.Context, notification Notification) ([]byte, error)
}
type NotificationRendererFunc ¶
type NotificationRendererFunc func(context.Context, Notification) ([]byte, error)
func (NotificationRendererFunc) RenderNotification ¶
func (f NotificationRendererFunc) RenderNotification(ctx context.Context, notification Notification) ([]byte, error)
type NotificationSender ¶
type NotificationSender interface {
SendNotification(ctx context.Context, delivery NotificationDelivery) error
}
NotificationSender is the only delivery integration required from a host using the PostgreSQL managed notification queue.
type NotificationSenderFunc ¶
type NotificationSenderFunc func(context.Context, NotificationDelivery) error
func (NotificationSenderFunc) SendNotification ¶
func (f NotificationSenderFunc) SendNotification(ctx context.Context, delivery NotificationDelivery) error
type NotificationTransaction
deprecated
type PasswordChangeStoreResult ¶
type PasswordChangeStoreResult struct {
Status PasswordChangeStoreStatus
Account Account
}
type PasswordChangeStoreStatus ¶
type PasswordChangeStoreStatus string
const ( PasswordChangeStoreSucceeded PasswordChangeStoreStatus = "succeeded" PasswordChangeStoreConflict PasswordChangeStoreStatus = "conflict" PasswordChangeStoreMissing PasswordChangeStoreStatus = "missing" )
type PasswordEmailChangeRequest ¶ added in v0.5.0
type PasswordEmailChangeRequest struct {
SubjectID SubjectID
CurrentPassword string
NewEmail string
}
PasswordEmailChangeRequest binds reauthentication to the actor selected by the trusted host. Never populate SubjectID from an unauthenticated request body.
type PasswordHasher ¶
type PasswordHasher interface {
HashPassword(password string) (string, error)
// VerifyPassword returns nil on a match and an error on a mismatch. Runtime
// preserves native mismatch errors as invalid credentials. Operational errors
// must wrap ErrPasswordVerificationUnavailable, ErrPasswordHashOverloaded,
// context.Canceled or context.DeadlineExceeded instead.
VerifyPassword(phc, password string) error
}
type PasswordInputPolicy ¶ added in v0.6.0
type PasswordInputPolicy string
PasswordInputPolicy describes verification of an existing credential, never issuance of a new password. The zero value retains the standard Unicode policy.
const ( PasswordInputPolicyUnicode PasswordInputPolicy = "unicode_v1" // PasswordInputPolicyLegacyBytes256 is only for explicitly imported Argon2id // v19 credentials with m=65536,t=3,p=1, a 16-byte salt and a 32-byte digest. PasswordInputPolicyLegacyBytes256 PasswordInputPolicy = "legacy_bytes_256" //nolint:gosec // Policy identifier, not a credential. )
type PasswordPolicy ¶
type PasswordPolicy struct {
MinLength int
MaxLength int
Blocklist CommonPasswordChecker
DisableBlocklist bool
}
func DefaultPasswordPolicy ¶
func DefaultPasswordPolicy() PasswordPolicy
func (PasswordPolicy) Validate ¶
func (p PasswordPolicy) Validate(password string) error
type PasswordResetConsumeRequest ¶
type PasswordResetConsumeRequest struct {
Selector string
Digest SecretDigest
PasswordPHC string
Now time.Time
}
type PasswordResetConsumeResult ¶
type PasswordResetConsumeResult struct {
Status PasswordResetConsumeStatus
Account Account
}
type PasswordResetConsumeStatus ¶
type PasswordResetConsumeStatus string
const ( PasswordResetConsumed PasswordResetConsumeStatus = "consumed" PasswordResetInvalid PasswordResetConsumeStatus = "invalid" PasswordResetExpired PasswordResetConsumeStatus = "expired" PasswordResetUsed PasswordResetConsumeStatus = "used" )
type PasswordResetReceipt ¶ added in v0.5.0
PasswordResetReceipt contains only public correlation identifiers, never a reset credential.
type PasswordResetRecipientResolver ¶ added in v0.7.0
type PasswordResetRecipientResolver interface {
LookupPasswordResetSubject(ctx context.Context, normalizedEmail string) (SubjectID, error)
ResolvePasswordResetRecipient(ctx context.Context, account Account, requestedEmail string) (string, error)
// PreparePasswordResetPassword applies host policy and returns a prepared PHC.
// Empty PHC with nil error selects the unchanged Runtime policy and hasher.
// It runs only after token authentication under the same subject lock. It
// must not mutate state or log/persist the supplied plaintext password.
PreparePasswordResetPassword(ctx context.Context, account Account, newPassword string) (string, error)
}
PasswordResetRecipientResolver is an optional, privileged host policy for recovery addresses. Lookup must find exactly one canonical subject across primary email and every host-authorized alias; missing or colliding ownership must return ErrAccountNotFound. Neither method may provision a local credential.
Resolve runs with the active canonical subject locked in the auth transaction. It must recheck current ownership and return the current authorized destination. A nonempty requestedEmail must still belong unambiguously to account.Subject.ID. Empty requestedEmail asks for the current password-reset success destination. Use the supplied context for all reads. Hosts must serialize alias mutations through the same subject lock and invalidate all reset records in that transaction, including change-away-and-back, before publishing the mutation.
type PasswordResetRecord ¶
type PasswordResetStore ¶
type PasswordResetStore interface {
CreatePasswordReset(ctx context.Context, record PasswordResetRecord) error
ConsumePasswordReset(ctx context.Context, request PasswordResetConsumeRequest) (PasswordResetConsumeResult, error)
}
type PasswordResetSubjectStore ¶ added in v0.7.0
type PasswordResetSubjectStore interface {
CreatePasswordResetForSubject(ctx context.Context, record PasswordResetRecord) error
// Authenticate and lock subject then token before prepare. Recheck expiry
// with the current configured clock after preparation and before mutation.
ConsumePasswordResetWithPreparation(ctx context.Context, request PasswordResetConsumeRequest,
prepare func(context.Context, Account) (string, error)) (PasswordResetConsumeResult, error)
}
PasswordResetSubjectStore is the opt-in storage capability required by PasswordResetRecipientResolver. The ordinary PasswordResetStore contract is unchanged. Implementations must lock the subject, require active status, a nonempty current local credential and the exact ExpectedSecurityVersion. ExpectedNormalizedEmail must be empty; it is not an alternate identity field. Replacement, single-use, expiry and transaction guarantees match CreatePasswordReset.
type PendingEmailChange ¶
type PendingEmailChange struct {
Scope EmailChangeScope `json:"-"`
ExpectedSecurityVersion int64 `json:"-"`
TargetSnapshot EmailChangeTargetSnapshot `json:"-"`
NewNormalizedValue string `json:"-"`
ID string
SubjectID SubjectID
NewDisplayValue string
Attempts int
MaxAttempts int
CreatedAt time.Time
ExpiresAt time.Time
}
type PreparedPasswordChange ¶ added in v0.8.0
type PreparedPasswordChange struct {
// contains filtered or unexported fields
}
PreparedPasswordChange is an opaque, runtime-bound proof of password verification and replacement hashing. It expires after five minutes. Hosts must keep it in process and must never log, serialize or send it to a client. Completion still requires host-owned session authorization.
func (PreparedPasswordChange) GoString ¶ added in v0.8.0
func (PreparedPasswordChange) GoString() string
GoString avoids exposing credential hashes through Go-syntax formatting.
func (PreparedPasswordChange) String ¶ added in v0.8.0
func (PreparedPasswordChange) String() string
String avoids exposing credential hashes through ordinary formatting.
type ProvisionLocalIdentityRequest ¶ added in v0.6.0
type ProvisionLocalIdentityRequest struct {
Identifier IdentifierInput
Password string
Profile BasicProfile
}
ProvisionLocalIdentityRequest creates an active email-less local identity. Identifier must use an explicitly registered non-email scheme.
type RateLimitPolicy ¶
func (RateLimitPolicy) Validate ¶
func (p RateLimitPolicy) Validate() error
type RateLimitRequest ¶
type RateLimitResult ¶
type RateLimitStore ¶
type RateLimitStore interface {
TakeRateLimit(ctx context.Context, request RateLimitRequest) (RateLimitResult, error)
}
type RefreshRotationRequest ¶
type RefreshRotationResult ¶
type RefreshRotationResult struct {
Status RefreshRotationStatus
Account Account
Session Session
FamilyID string
}
type RefreshRotationStatus ¶
type RefreshRotationStatus string
const ( RefreshRotationSucceeded RefreshRotationStatus = "succeeded" RefreshRotationInvalid RefreshRotationStatus = "invalid" RefreshRotationExpired RefreshRotationStatus = "expired" RefreshRotationRevoked RefreshRotationStatus = "revoked" RefreshRotationReplayed RefreshRotationStatus = "replayed" )
type RegisterRequest ¶
type RegisterRequest struct {
Email string
Password string
Profile BasicProfile
}
type RegisterResult ¶
type RenameLocalIdentityRequest ¶ added in v0.6.0
type RenameLocalIdentityRequest struct {
SubjectID SubjectID
ExpectedIdentifier IdentifierInput
ExpectedSecurityVersion int64
NewIdentifier IdentifierInput
}
RenameLocalIdentityRequest binds a custom login edit to the exact subject and security version the host authorized. Both identifiers use the same explicit, registered non-email scheme. ExpectedIdentifier is compared after normalization.
type RenameLocalIdentityStoreRequest ¶ added in v0.6.0
type RenameLocalIdentityStoreRequest struct {
SubjectID SubjectID
Scheme IdentifierScheme
ExpectedNormalizedValue string
ExpectedSecurityVersion int64
NewDisplayValue string
NewNormalizedValue string
Now time.Time
}
RenameLocalIdentityStoreRequest contains already normalized, bounded values. Stores must validate these bounds and the expected state under a subject lock.
type RetireLocalIdentityRequest ¶ added in v0.6.0
type RetireLocalIdentityRequest struct {
SubjectID SubjectID
ExpectedIdentifier IdentifierInput
ExpectedSecurityVersion int64
}
RetireLocalIdentityRequest authorizes terminal retirement of the ENTIRE authentication subject, releasing only this primary custom login. Other identifiers and external links remain reserved to the disabled old subject.
type RetireLocalIdentityStoreRequest ¶ added in v0.6.0
type RetireLocalIdentityStoreRequest struct {
SubjectID SubjectID
Scheme IdentifierScheme
ExpectedNormalizedValue string
ExpectedSecurityVersion int64
Now time.Time
}
RetireLocalIdentityStoreRequest contains an explicit non-email scheme and normalized, bounded expected login. Now must be nonzero.
type Runtime ¶
type Runtime struct {
// contains filtered or unexported fields
}
func NewRuntime ¶
func (*Runtime) AcknowledgeEncryptedEvent ¶
func (*Runtime) AuthenticateSession ¶ added in v0.5.0
AuthenticateSession validates current session/security state and realm membership.
func (*Runtime) BeginLocalLogin ¶ added in v0.8.0
func (r *Runtime) BeginLocalLogin(ctx context.Context, request LoginRequest, binding [32]byte) (LocalLoginResult, error)
BeginLocalLogin returns either final local tokens or a non-authorizing pending selector. Hosts keep it separate from authenticated browser state and enforce their authoritative browser-flow publication fence before exposing tokens.
func (*Runtime) BeginLocalLoginEnrollment ¶ added in v0.8.0
func (r *Runtime) BeginLocalLoginEnrollment(ctx context.Context, id string, binding [32]byte) (MFAEnrollment, error)
BeginLocalLoginEnrollment only accepts a live password-verified enrollment continuation. It never creates a session or extends the original deadline.
func (*Runtime) BeginMFAEnrollment ¶ added in v0.8.0
func (r *Runtime) BeginMFAEnrollment(ctx context.Context, request MFAEnrollmentRequest) (MFAEnrollment, error)
func (*Runtime) CancelMFAEnrollment ¶ added in v0.8.0
func (*Runtime) ChangePassword ¶
func (*Runtime) CleanupExpiredEncryptedEvents ¶
func (*Runtime) CompleteLocalLogin ¶ added in v0.8.0
func (r *Runtime) CompleteLocalLogin(ctx context.Context, id string, binding [32]byte, code string) (LoginResult, error)
CompleteLocalLogin prepares tokens before writes, then rechecks and consumes the factor/challenge with session and audit in one owned commit. Expected denials commit their durable attempt effects; errors release no usable result.
func (*Runtime) CompleteLocalLoginEnrollment ¶ added in v0.8.0
func (r *Runtime) CompleteLocalLoginEnrollment( ctx context.Context, id, enrollmentID string, binding [32]byte, code string, ) (LoginResult, error)
CompleteLocalLoginEnrollment atomically activates the displayed setup, invalidates previous authority and publishes a fresh post-enrollment session. No authority or recovery codes are returned for an uncertain commit.
func (*Runtime) CompletePasswordChange ¶ added in v0.8.0
func (r *Runtime) CompletePasswordChange(ctx context.Context, subjectID SubjectID, proof *PreparedPasswordChange, ) (Account, error)
CompletePasswordChange joins the host auth transaction, revalidates the proof under the subject lock, and performs the existing atomic password update, session invalidation, notification and audit. The host must authorize its current live session and any required second factor in this same transaction. The expected subject prevents a proof from being applied to a different actor. Success inside an outer transaction is provisional until that owner commits.
func (*Runtime) ConfirmEmailChange ¶
func (*Runtime) ConfirmMFAEnrollment ¶ added in v0.8.0
func (*Runtime) DecryptNotificationEvent ¶
func (r *Runtime) DecryptNotificationEvent(event EncryptedEvent) (Notification, error)
func (*Runtime) DisableMFA ¶ added in v0.8.0
func (r *Runtime) DisableMFA(ctx context.Context, request MFAChangeRequest) error
func (*Runtime) FindAccount ¶
func (*Runtime) GetAccount ¶
func (*Runtime) GetLocalIdentifier ¶ added in v0.6.0
func (r *Runtime) GetLocalIdentifier(ctx context.Context, subjectID SubjectID, scheme IdentifierScheme) (Identifier, error)
GetLocalIdentifier reads a primary custom login by immutable subject ID. It exposes neither passwords nor password policy, and does not require a credential. The scheme must be explicitly registered and non-email; absence is a conflict.
func (*Runtime) GetSubjectLifecycle ¶ added in v0.6.0
func (r *Runtime) GetSubjectLifecycle(ctx context.Context, id SubjectID) (SubjectLifecycleView, error)
GetSubjectLifecycle reads lifecycle by immutable subject ID. It is suitable for host reconciliation, but is not an operation receipt or proof of which request committed. It exposes no credentials.
func (*Runtime) ImportLocalIdentity ¶ added in v0.6.0
func (r *Runtime) ImportLocalIdentity(ctx context.Context, request ImportLocalIdentityRequest) (Account, error)
ImportLocalIdentity is a privileged, create-only migration API. It never overwrites passwords, re-enables subjects, or merges identities by identifier. The host must atomically persist its import mapping and grants using the same AuthTransaction and skip already mapped imports, preserving later mutations. A conflict is an error, including a repeated call with the same subject ID.
func (*Runtime) LinkExternalIdentity ¶
func (r *Runtime) LinkExternalIdentity(ctx context.Context, auth AuthContext, external ExternalIdentity) (IdentityLink, error)
func (*Runtime) Login ¶
func (r *Runtime) Login(ctx context.Context, request LoginRequest) (LoginResult, error)
func (*Runtime) LoginExternal ¶
func (r *Runtime) LoginExternal(ctx context.Context, request ExternalLoginRequest) (LoginResult, error)
LoginExternal resolves or provisions an SSO-only account and creates a realm-bound session. An unverified email can receive only the user realm's limited confirmation session.
func (*Runtime) MFAStatus ¶ added in v0.8.0
MFAStatus reports enrollment and whether local MFA management is available. A missing codec still returns the authorized enrollment state with ErrMFAUnavailable.
func (*Runtime) PendingEmailChange ¶
func (*Runtime) PreparePasswordChange ¶ added in v0.8.0
func (r *Runtime) PreparePasswordChange(ctx context.Context, request ChangePasswordRequest) (*PreparedPasswordChange, error)
PreparePasswordChange performs durable password-attempt admission and hashing outside a host transaction. SubjectID must come from the authenticated actor, never from an unauthenticated form. No plaintext password is retained.
func (*Runtime) PreparePasswordChangeWithIssuer ¶ added in v0.8.0
func (r *Runtime) PreparePasswordChangeWithIssuer(ctx context.Context, request ChangePasswordRequest, issuer *Runtime, ) (*PreparedPasswordChange, error)
PreparePasswordChangeWithIssuer uses a trusted host-selected runtime only for replacement policy and bounded hashing. Current-credential verification, durable admission, proof binding, notification and audit remain with r. Never select the issuer from request input. It grants no account-write authority.
func (*Runtime) ProvisionExternalIdentity ¶ added in v0.12.0
func (r *Runtime) ProvisionExternalIdentity(ctx context.Context, external ExternalIdentity) (Account, error)
ProvisionExternalIdentity resolves an exact existing issuer/subject binding or creates a new SSO-only account. Unlike ResolveExternalIdentity, it NEVER links by email, regardless of AutoLinkVerifiedEmailIssuers. Email collisions require the separate authenticated explicit-link workflow.
This is a trusted host API, not an HTTP signup endpoint. The caller MUST verify the provider proof, project admission and enrollment policy before calling it. It grants no membership, roles, password or session. Hosts must join this call, their enrollment record and mandatory audit in one owned auth transaction, and withhold a successful result until the outer commit is confirmed.
func (*Runtime) ProvisionLocalIdentity ¶ added in v0.6.0
func (r *Runtime) ProvisionLocalIdentity(ctx context.Context, request ProvisionLocalIdentityRequest) (Account, error)
ProvisionLocalIdentity is a privileged host API. Authorize the operator before calling it; do not bind public signup input to it. It creates no session and asserts no verified email. Account creation and audit join AuthTransaction.
func (*Runtime) ProvisionTrustedLocalAccount ¶
func (r *Runtime) ProvisionTrustedLocalAccount(ctx context.Context, request RegisterRequest) (Account, error)
ProvisionTrustedLocalAccount creates a verified local account for an operator-controlled bootstrap or seed path. Interactive registration must use Register so that the account starts in confirmation scope.
func (*Runtime) RegenerateMFARecovery ¶ added in v0.8.0
func (*Runtime) Register ¶
func (r *Runtime) Register(ctx context.Context, request RegisterRequest) (RegisterResult, error)
func (*Runtime) RenameLocalIdentity ¶ added in v0.6.0
func (r *Runtime) RenameLocalIdentity(ctx context.Context, request RenameLocalIdentityRequest) (LocalIdentityView, error)
RenameLocalIdentity is a privileged host operation, with no public endpoint or notification. Authorize the exact subject and rate-limit the operator first. Original display spelling is preserved; the registered resolver defines equality. Display-only edits also advance security version; an exact no-op is an error. Old login is immediately released, so reuse must create a fresh subject.
Call before host project locks. Results inside an outer AuthTransaction are provisional until that transaction succeeds. ErrOperationOutcomeUnknown returns no success; reconcile a durable host receipt before retrying. Version increments invalidate existing bindings but do not close OIDC provider final-write races.
func (*Runtime) RequestEmailChange ¶
func (r *Runtime) RequestEmailChange(ctx context.Context, subjectID SubjectID, newEmail string) error
RequestEmailChange is a trusted host API. The host must authorize the actor and require fresh authentication before calling it. Local-password HTTP flows should use RequestEmailChangeWithPassword instead.
func (*Runtime) RequestEmailChangeWithPassword ¶ added in v0.5.0
func (r *Runtime) RequestEmailChangeWithPassword(ctx context.Context, request PasswordEmailChangeRequest) error
RequestEmailChangeWithPassword verifies this subject's current local password before issuing an email-change challenge. The caller still owns session and actor-to-target authorization. SSO-only accounts need an explicit host-owned recent-IdP-authentication flow through RequestEmailChange; there is no fallback.
func (*Runtime) RequestEmailChangeWithPreviousEmailNotice ¶ added in v0.14.0
func (r *Runtime) RequestEmailChangeWithPreviousEmailNotice( ctx context.Context, subjectID SubjectID, newEmail, previousEmail string, ) error
RequestEmailChangeWithPreviousEmailNotice is a trusted host API. Like RequestEmailChange, the host must authorize the actor and require fresh authentication. previousEmail must be a canonical, already verified host address read under the same auth transaction, never an untrusted form value. A nonempty value must exactly match the locked pre-change target snapshot. Empty retains the existing RequestEmailChange behavior. A successful issuance atomically queues a credential-free notice; no mail is sent in the transaction. An uncertain commit must not be blindly retried as a new issuance.
func (*Runtime) RequestPasswordReset ¶
func (*Runtime) RequestPasswordResetWithReceipt ¶ added in v0.5.0
func (r *Runtime) RequestPasswordResetWithReceipt( ctx context.Context, email string, bind func(context.Context, PasswordResetReceipt) error, ) error
RequestPasswordResetWithReceipt calls bind inside the initiating auth transaction after reset, encrypted notification and audit writes. A bind error rolls back all participating writes. No callback runs when no reset is issued. Privileged hosts must not expose whether bind ran to unauthenticated clients.
func (*Runtime) ResetPassword ¶
func (*Runtime) ResolveExternalIdentity ¶
func (r *Runtime) ResolveExternalIdentity(ctx context.Context, external ExternalIdentity) (Account, error)
ResolveExternalIdentity accepts only identity claims verified by a trusted provider adapter. Never bind unverified client JSON directly to this method.
func (*Runtime) RetireLocalIdentity ¶ added in v0.6.0
func (r *Runtime) RetireLocalIdentity(ctx context.Context, request RetireLocalIdentityRequest) (SubjectLifecycleView, error)
RetireLocalIdentity is a privileged host operation, without an HTTP endpoint or email notification. Authorize the exact subject, login and security version and rate-limit the operator first. This permanently retires the whole auth subject, not only an alias. Reusing the released login creates a fresh subject with no inherited grants, roles, sessions or links. Retained emails can prevent reuse and must never silently bind the replacement to the former subject.
Call before host project locks and compose grants/audit/operation receipt in the same AuthTransaction. Nested results are provisional until outer commit. Every error returns zero success. ErrOperationOutcomeUnknown needs durable receipt reconciliation; do not blindly retry. Repeated retirement returns ErrSubjectRetired without writes. This does not close OIDC final-write races.
func (*Runtime) SendEmailChallenge ¶
func (*Runtime) SetSubjectStatus ¶
func (*Runtime) SetTrustedLocalPassword ¶ added in v0.6.0
func (r *Runtime) SetTrustedLocalPassword(ctx context.Context, request SetTrustedLocalPasswordRequest) (Account, error)
SetTrustedLocalPassword is a privileged host API, never a public reset endpoint. The host must authorize and rate-limit its operator and supply actor audit. Strict issuance policy and the shared hash budget apply; authentication-attempt admission does not. Even identical plaintext advances security version and revokes security state. Active, suspended and disabled status are preserved.
Hashing precedes new locks. Call before taking host project locks. This joins an outer AuthTransaction: returned state is provisional until that outer call succeeds. Reconcile a durable host operation record on ErrOperationOutcomeUnknown before retrying, since a repeated successful call advances security state again. Required delivery enqueues password_changed only when a primary email exists; disabled delivery/email-less identities still require transactional audit.
func (*Runtime) UpdateBasicProfile ¶
func (*Runtime) VerifyAccessToken
deprecated
func (*Runtime) VerifyCredential ¶
VerifyCredential verifies a local credential without creating a session. It is intended for recent-authentication checks and trusted bootstrap flows.
func (*Runtime) VerifyEmailChallenge ¶
type RuntimeStore ¶
type RuntimeStore interface {
AccountStore
SessionStore
PasswordResetStore
EmailChallengeStore
EmailChangeStore
IdentityLinkStore
RateLimitStore
}
type SSOAccountRecord ¶
type SSOAccountRecord struct {
Account Account
Link IdentityLink
}
type ScopedEmailChangeStore ¶ added in v0.8.0
type ScopedEmailChangeStore interface {
IssueScopedEmailChange(ctx context.Context, record EmailChangeRecord,
limits EmailChallengeLimits) (EmailChangeIssueResult, error)
GetPendingScopedEmailChange(ctx context.Context, subject SubjectID,
scope EmailChangeScope, now time.Time) (PendingEmailChange, error)
VerifyScopedEmailChange(ctx context.Context, request EmailChangeVerifyRequest) (EmailChangeVerifyResult, error)
}
ScopedEmailChangeStore is an explicit opt-in. Legacy RuntimeStore adapters cannot silently treat a host projection as the primary email. Implementations share the ordinary subject-wide issuance quota and record-attempt machinery.
type SecretDigest ¶
type SecurityEvent ¶
type SecurityEventType ¶
type SecurityEventType string
const ( SecurityEventLocalIdentityProvisioned SecurityEventType = "local_identity.provisioned" SecurityEventLocalIdentityImported SecurityEventType = "local_identity.imported" SecurityEventLoginFailed SecurityEventType = "login.failed" SecurityEventRefreshReplay SecurityEventType = "refresh.replay" SecurityEventPasswordResetIssued SecurityEventType = "password_reset.issued" SecurityEventPasswordResetUsed SecurityEventType = "password_reset.used" SecurityEventPasswordChanged SecurityEventType = "password.changed" SecurityEventTrustedLocalPasswordSet SecurityEventType = "password.trusted_set" SecurityEventLocalIdentityRenamed SecurityEventType = "local_identity.renamed" SecurityEventSubjectRetired SecurityEventType = "subject.retired" SecurityEventEmailChallengeIssued SecurityEventType = "email_challenge.issued" SecurityEventEmailVerified SecurityEventType = "email.verified" SecurityEventEmailChangeIssued SecurityEventType = "email_change.issued" SecurityEventEmailChanged SecurityEventType = "email.changed" SecurityEventSessionRevoked SecurityEventType = "session.revoked" SecurityEventSessionsRevoked SecurityEventType = "sessions.revoked" SecurityEventSubjectStatusChanged SecurityEventType = "subject.status_changed" SecurityEventIdentityLinked SecurityEventType = "identity.linked" )
type Session ¶
type SessionRecord ¶
type SessionScope ¶
type SessionScope string
const ( SessionScopeAuthenticated SessionScope = "authenticated" SessionScopeConfirmation SessionScope = "confirmation" )
type SessionSecurity ¶
type SessionSecurity struct {
Session Session
SubjectStatus SubjectStatus
CurrentVersion int64
}
type SessionStore ¶
type SessionStore interface {
// PeekRefresh authenticates a token without consuming it. Rotation revalidates all state.
PeekRefresh(ctx context.Context, request RefreshRotationRequest) (RefreshRotationResult, error)
// CreateSession locks the canonical subject and rejects stale status, security
// version, or email-verification/scope state. It must not rewrite signed scope.
CreateSession(ctx context.Context, record SessionRecord) error
RotateRefresh(ctx context.Context, request RefreshRotationRequest) (RefreshRotationResult, error)
IntrospectSession(ctx context.Context, sessionID string) (SessionSecurity, error)
RevokeSession(ctx context.Context, subjectID SubjectID, sessionID string, now time.Time) (bool, error)
RevokeSubjectSessions(ctx context.Context, subjectID SubjectID, now time.Time) (int64, error)
SetSubjectStatus(ctx context.Context, subjectID SubjectID, status SubjectStatus, now time.Time) (Subject, error)
}
type SetTrustedLocalPasswordRequest ¶ added in v0.6.0
SetTrustedLocalPasswordRequest replaces an existing local credential without its old password. It never creates a credential or changes subject status.
type SigningConfig ¶
type Subject ¶
type Subject struct {
ID SubjectID
Status SubjectStatus
SecurityVersion int64
CreatedAt time.Time
UpdatedAt time.Time
}
Subject is the canonical security principal. Profile, identifiers, credentials, memberships, and permissions deliberately live elsewhere.
type SubjectID ¶
SubjectID is the canonical identifier shared by every goauth relation.
func MustParseSubjectID ¶
func NewSubjectID ¶
func NewSubjectID() SubjectID
func ParseSubjectID ¶
func (SubjectID) MarshalText ¶
func (*SubjectID) UnmarshalText ¶
type SubjectLifecycleReader ¶ added in v0.6.0
type SubjectLifecycleReader interface {
GetSubjectLifecycle(ctx context.Context, subjectID SubjectID) (SubjectLifecycleView, error)
}
SubjectLifecycleReader is an optional capability. Read account and marker from ONE consistent snapshot by immutable subject ID, including retired accounts. Reads join AuthTransaction and reject foreign transaction scopes.
type SubjectLifecycleView ¶ added in v0.6.0
SubjectLifecycleView is a non-secret, consistent snapshot of an account and its terminal retirement marker. Subject's existing struct layout is unchanged. RetiredAt is nil for ordinary active, suspended and disabled accounts.
type SubjectStatus ¶
type SubjectStatus string
const ( SubjectStatusActive SubjectStatus = "active" SubjectStatusSuspended SubjectStatus = "suspended" SubjectStatusDisabled SubjectStatus = "disabled" )
func (SubjectStatus) Validate ¶
func (s SubjectStatus) Validate() error
type TrustedLocalPasswordStore ¶ added in v0.6.0
type TrustedLocalPasswordStore interface {
SetTrustedLocalPassword(ctx context.Context, request TrustedLocalPasswordStoreRequest) (Account, error)
}
TrustedLocalPasswordStore is an optional RuntimeStore capability. A successful write must preserve subject status, replace only an existing credential, set its input policy to Unicode, increment security version, and invalidate all sessions, local/OIDC refresh families, resets and pending email security state. Writes must join AuthTransaction, including mandatory Runtime audit/enqueue. Missing subjects/credentials return ErrAccountNotFound. Stale security version returns ErrSecurityVersionMismatch; stale PHC/policy returns ErrPasswordChangeConflict.
type TrustedLocalPasswordStoreRequest ¶ added in v0.6.0
type TrustedLocalPasswordStoreRequest struct {
SubjectID SubjectID
ExpectedPasswordPHC string
ExpectedPasswordInputPolicy PasswordInputPolicy
ExpectedSecurityVersion int64
NewPasswordPHC string
Now time.Time
}
TrustedLocalPasswordStoreRequest binds a privileged replacement to the exact credential and security state read before hashing. All expected fields must be checked under the canonical subject lock, then the credential lock.
type URLBuilder ¶
type URLBuilderFunc ¶
func (URLBuilderFunc) PasswordResetURL ¶
Source Files
¶
- account.go
- assisted_recovery.go
- contracts.go
- crypto.go
- email_change.go
- email_change_scope.go
- errors.go
- external_provision.go
- identifier.go
- identity.go
- jwt.go
- local_common_passwords.go
- local_identity.go
- local_identity_rename.go
- login_session.go
- mfa_enrollment.go
- mfa_enrollment_contract.go
- mfa_factor.go
- mfa_login.go
- mfa_login_contract.go
- mfa_login_enrollment.go
- mfa_required.go
- notifications.go
- password.go
- password_compatibility.go
- password_import.go
- password_reset_recipient.go
- password_reset_scope.go
- rate_limit.go
- reauthentication.go
- recovery.go
- runtime.go
- security_transaction.go
- subject_retirement.go
- trusted_local_password.go
- types.go
Directories
¶
| Path | Synopsis |
|---|---|
|
cmd
|
|
|
externalconsumerprobe
command
|
|
|
releaseevidence
command
Command releaseevidence validates a complete public-preview evidence manifest.
|
Command releaseevidence validates a complete public-preview evidence manifest. |
|
examples
|
|
|
hostsession
command
Command hostsession demonstrates email-less credentials with host-owned sessions.
|
Command hostsession demonstrates email-less credentials with host-owned sessions. |
|
nethttp
command
Command nethttp demonstrates host-owned browser transport and bearer-only API routes backed by a single PostgreSQL Runtime.
|
Command nethttp demonstrates host-owned browser transport and bearer-only API routes backed by a single PostgreSQL Runtime. |
|
internal
|
|
|
authclock
Package authclock carries the Runtime clock across its transaction boundary.
|
Package authclock carries the Runtime clock across its transaction boundary. |
|
identifierbounds
Package identifierbounds enforces portable custom identifier storage bounds.
|
Package identifierbounds enforces portable custom identifier storage bounds. |
|
retryafter
Package retryafter extracts a transport-independent retry deadline.
|
Package retryafter extracts a transport-independent retry deadline. |
|
Package nethttp adapts goauth to standard-library JSON HTTP handlers.
|
Package nethttp adapts goauth to standard-library JSON HTTP handlers. |
|
reference
|
|
|
externalconsumer
Package externalconsumer is a compile-checked manifest of the goauth packages that are currently supported for external consumers such as backend and goadmin.
|
Package externalconsumer is a compile-checked manifest of the goauth packages that are currently supported for external consumers such as backend and goadmin. |