Documentation
¶
Overview ¶
Package sigil provides the experimental embedded Sigil authentication foundation: immutable configuration, lifecycle and actor-authorized service contracts. Storage and authentication flows are not implemented yet. See docs/core-contracts.md for ownership, cancellation and trust boundaries.
Index ¶
- Constants
- Variables
- func Describe(c Config) (contract.Document, error)
- func ImpersonatorFromContext(ctx context.Context) (string, bool)
- func IsAccountSuspended(err error) bool
- func IsEmailTaken(err error) bool
- func Refuse(reason AuditReason, err *Error) error
- func Version() string
- func WithAuditMethod(ctx context.Context, method AuditMethod) context.Context
- type AbuseConfig
- type AbuseFlow
- type AbusePolicy
- type AbuseService
- type Account
- type AdminService
- func (s AdminService) Account(ctx context.Context, userID string) (Account, error)
- func (s AdminService) CompleteStepUp(ctx context.Context, method AuditMethod, ...) (IssuedSession, error)
- func (s AdminService) CreateUser(ctx context.Context, input CreateUser) (User, error)
- func (s AdminService) DeleteUser(ctx context.Context, userID string) error
- func (s AdminService) Impersonate(ctx context.Context, targetID string, duration time.Duration) (IssuedSession, error)
- func (s AdminService) IssueSession(ctx context.Context, userID string, method AuditMethod) (IssuedSession, error)
- func (s AdminService) Operator(ctx context.Context, p OperatorPolicy) (context.Context, error)
- func (s AdminService) Reinstate(ctx context.Context, userID string) error
- func (s AdminService) RevokeAllSessions(ctx context.Context, userID string) error
- func (s AdminService) RevokeSession(ctx context.Context, userID, sessionID string) error
- func (s AdminService) Sessions(ctx context.Context, userID, afterID string, limit int) ([]Session, error)
- func (s AdminService) Suspend(ctx context.Context, userID string) error
- func (s AdminService) VerifyAndIssueSession(ctx context.Context, userID string, method AuditMethod, ...) (IssuedSession, error)
- type AssuranceLevel
- type AssurancePolicy
- type AssuranceRequirement
- type AuditEvent
- type AuditFailure
- type AuditMethod
- type AuditQuery
- type AuditReason
- type AuditService
- type Auth
- func (a *Auth) Abuse() AbuseService
- func (a *Auth) Admin() AdminService
- func (a *Auth) Audit() AuditService
- func (a *Auth) AuthenticateRequest(r *http.Request) (*http.Request, error)
- func (a *Auth) Close(ctx context.Context) error
- func (a *Auth) Contract() contract.Document
- func (a *Auth) Credentials() CredentialsService
- func (a *Auth) Deployment() Deployment
- func (a *Auth) EndImpersonation(w http.ResponseWriter, r *http.Request) error
- func (a *Auth) Handler() http.Handler
- func (a *Auth) Passwords() PasswordsService
- func (a *Auth) PluginIDs() []string
- func (a *Auth) ProtocolRequest(r *http.Request, origin string) (*http.Request, netip.Addr, error)
- func (a *Auth) RequireSession(next http.Handler) http.Handler
- func (a *Auth) Retention() RetentionService
- func (a *Auth) SafeRedirect(target string) (string, error)
- func (a *Auth) ServesOrigin(origin string) bool
- func (a *Auth) Sessions() SessionsService
- func (a *Auth) SetSessionCookie(w http.ResponseWriter, issued IssuedSession) error
- func (a *Auth) StartImpersonation(w http.ResponseWriter, r *http.Request, targetID string, ...) (IssuedSession, error)
- func (a *Auth) Users() UsersService
- func (a *Auth) WithAdministration(ctx context.Context, operation plugin.Operation, userID string, ...) error
- func (a *Auth) WithAdministrationTx(ctx context.Context, operation plugin.Operation, fn func(storage.Tx) error) error
- func (a *Auth) WithAssurance(ctx context.Context, op plugin.Operation, r AssuranceRequirement, ...) error
- func (a *Auth) WithCredential(ctx context.Context, operation plugin.Operation, credential AuditMethod, ...) error
- func (a *Auth) WithNewAccount(ctx context.Context, operation plugin.Operation, input CreateUser, ...) (User, error)
- func (a *Auth) WithRecentSession(ctx context.Context, operation plugin.Operation, ...) error
- type AuthenticationState
- type Clock
- type Code
- type Config
- type CookieConfig
- type CreateUser
- type Credentials
- type CredentialsService
- func (s CredentialsService) ChangePassword(ctx context.Context, ip netip.Addr, current, password Secret) error
- func (s CredentialsService) ConfirmEmailChange(ctx context.Context, ip netip.Addr, token Secret) error
- func (s CredentialsService) Register(ctx context.Context, ip netip.Addr, input Credentials) error
- func (s CredentialsService) RequestEmailChange(ctx context.Context, ip netip.Addr, target string) error
- func (s CredentialsService) RequestPasswordReset(ctx context.Context, ip netip.Addr, target string) error
- func (s CredentialsService) ResendVerification(ctx context.Context, ip netip.Addr, target string) error
- func (s CredentialsService) ResetPassword(ctx context.Context, ip netip.Addr, token, password Secret) error
- func (s CredentialsService) SignIn(ctx context.Context, ip netip.Addr, input Credentials) (IssuedSession, error)
- func (s CredentialsService) VerifyEmail(ctx context.Context, ip netip.Addr, token Secret) error
- type Deployment
- type Error
- type ImpersonationPolicy
- type IssuedSession
- type LocalMailSink
- type Mail
- type MailDelivery
- func (d *MailDelivery) Cleanup(ctx context.Context, limit int) (int64, error)
- func (d *MailDelivery) DispatchOne(ctx context.Context) (bool, error)
- func (d *MailDelivery) Enqueue(ctx context.Context, tx storage.Tx, id string, template MailTemplate, ...) error
- func (d *MailDelivery) Rotate(ctx context.Context, cursor string, limit int) (Rotation, error)
- type MailSender
- type MailTemplate
- type OperatorPolicy
- type PasswordVerification
- type PasswordsService
- type ProtectionBinding
- type Protector
- type Pruned
- type RegistrationConfig
- type RequestContext
- type RetentionService
- type RetryError
- type Rotation
- type Rotator
- type Secret
- type SecretSource
- type Session
- type SessionConfig
- type SessionView
- type SessionsService
- func (s SessionsService) Authenticate(ctx context.Context, token Secret) (context.Context, error)
- func (s SessionsService) Authentication(ctx context.Context) (SessionView, error)
- func (s SessionsService) Current(ctx context.Context) (SessionView, error)
- func (s SessionsService) EndImpersonation(ctx context.Context) error
- func (s SessionsService) List(ctx context.Context, afterID string, limit int) ([]Session, error)
- func (s SessionsService) Renew(ctx context.Context) (SessionView, error)
- func (s SessionsService) RequireAssurance(ctx context.Context, r AssuranceRequirement) error
- func (s SessionsService) RequireRecent(ctx context.Context, maxAge time.Duration) error
- func (s SessionsService) RevokeAll(ctx context.Context) error
- func (s SessionsService) RevokeCurrent(ctx context.Context) error
- type StartupChecker
- type User
- type UsersService
Constants ¶
const ( // MaxPasswordBytes bounds input before UTF-8 scanning or copying. MaxPasswordBytes = 1024 // MinPasswordRunes applies to new passwords, not historical verification. MinPasswordRunes = 15 )
Variables ¶
var ( ErrRateLimited = &Error{Code: CodeRateLimited, Message: "too many attempts"} ErrOverloaded = &Error{Code: CodeOverloaded, Message: "authentication capacity exhausted"} ErrInvalidConfiguration = &Error{Code: CodeInvalidConfiguration, Message: "invalid configuration"} ErrUnauthenticated = &Error{Code: CodeUnauthenticated, Message: "authentication required"} ErrAssuranceRequired = &Error{Code: CodeAssuranceRequired, Message: "stronger authentication required"} ErrForbidden = &Error{Code: CodeForbidden, Message: "operation forbidden"} ErrRecentAuthenticationRequired = &Error{Code: CodeRecentAuthenticationRequired, Message: "recent authentication required"} ErrClosed = &Error{Code: CodeClosed, Message: "authentication service is closed"} ErrBadRequest = &Error{Code: CodeBadRequest, Message: "invalid request"} ErrNotFound = &Error{Code: CodeNotFound, Message: "endpoint not found"} ErrMethodNotAllowed = &Error{Code: CodeMethodNotAllowed, Message: "method not allowed"} ErrBodyTooLarge = &Error{Code: CodeBodyTooLarge, Message: "request body too large"} ErrUnsupportedMediaType = &Error{Code: CodeUnsupportedMediaType, Message: "unsupported content type"} )
var ErrDelivery = errors.New("sigil: email delivery failed")
var ErrProtection = errors.New("sigil: secret protection failed")
Functions ¶
func Describe ¶
Describe exports the API contract for a configuration without side effects. It compiles the plugin registry and resolves the browser cookie policy, and reads nothing else: no storage connection, secret load, startup check or mail. The same description is validated by New, so a configuration that starts also exports, and an export never requires production credentials.
func ImpersonatorFromContext ¶
ImpersonatorFromContext returns the operator's user ID when ctx's validated session is an impersonation session. The session's user is the target. Hosts use it to show that a session is impersonated and to refuse their own sensitive actions, as the library refuses its own.
func IsAccountSuspended ¶
IsAccountSuspended reports whether a direct call failed only because its account is suspended. The error still matches ErrUnauthenticated and HTTP responses never distinguish it; hosts may use this to explain the refusal to a caller they have otherwise authenticated, and plugins use it to avoid recording a second failure event for the same attempt.
func IsEmailTaken ¶
IsEmailTaken reports whether WithNewAccount failed only because another account already has the address. It still matches ErrBadRequest.
func Refuse ¶
func Refuse(reason AuditReason, err *Error) error
Refuse returns an error that a transactional callback of WithCredential, WithAssurance, WithRecentSession or WithAdministration returns to reject the operation while committing what it already wrote, such as revoking the tokens a replayed authorization code minted. The operation's failure event, with reason, commits in the same transaction in place of its success event; plugin hooks do not run; the caller receives err. Use it only when the rejection itself must change state; every other rejection rolls back, as a refusal does under an empty operation.
func Version ¶
func Version() string
Version reports the release this build was compiled from, exactly as the Go toolchain recorded it and with the leading "v" the module version carries, so it is the Git tag rather than a transformation of it. It is empty when the toolchain had nothing to record.
Nothing in the repository states a release number. The tag is the only source of truth, which is why no file has to be remembered at release time and why nothing can disagree with the tag. The cost is that this is best-effort: it reports a published version to a consumer who resolved one, a pseudo-version with a "+dirty" suffix inside a working checkout, and nothing at all under `go run`, in a test binary, with -buildvcs=false, or when a replace directive reaches this module. Log it; never decide on it.
Compatibility for each surface is docs/versioning.md.
func WithAuditMethod ¶
func WithAuditMethod(ctx context.Context, method AuditMethod) context.Context
WithAuditMethod names, for events recorded under ctx, the credential or method an operation concerns, such as "api_key.<id>" for a session-authorized API-key issuance. It is for trusted code only; flows that establish their own sign-in method override it. The value must match ^[a-z][a-z0-9_.-]{0,79}$ or the operation fails as a bad request when its event is written.
Types ¶
type AbuseConfig ¶
type AbuseConfig struct {
Store storage.AbuseStore
Policies map[AbuseFlow]AbusePolicy
MaxRequests, MaxExpensive int
}
AbuseConfig limits each Auth instance's active requests and expensive work. There are no waiting queues. Store defaults to Config.Store when supported; without a shared store, protected operations fail closed (including in development). All replicas must use identical secrets and policies.
type AbuseFlow ¶
type AbuseFlow string
const ( AbuseRequest AbuseFlow = "request" AbuseSignIn AbuseFlow = "sign_in" AbuseRegistration AbuseFlow = "registration" AbuseRecovery AbuseFlow = "recovery" AbuseVerification AbuseFlow = "verification" AbuseToken AbuseFlow = "token" AbuseMail AbuseFlow = "mail" // AbuseClient budgets the authentication of machine callers, such as an // authorization server's clients and resource servers, per address and // per client identifier. Its defaults suit steady machine traffic. AbuseClient AbuseFlow = "client" )
type AbusePolicy ¶
type AbusePolicy struct{ IPAttempts, IdentifierAttempts int }
type AbuseService ¶
type AbuseService struct {
// contains filtered or unexported fields
}
func (AbuseService) Do ¶
func (s AbuseService) Do(ctx context.Context, flow AbuseFlow, ip netip.Addr, identifier string, expensive bool, work func(context.Context) error) error
Do reserves local capacity, consumes shared budgets, then runs work once. The callback must honor context cancellation; slots remain held until it returns. Use expensive=false with Passwords(), which acquires its own KDF slot. Use expensive=true for other expensive callbacks. A flow inside the HTTP request callback reuses its request slot, as do nested service flow budgets. Do not recursively nest expensive work.
type AdminService ¶
type AdminService struct {
// contains filtered or unexported fields
}
AdminService is a host-only capability for explicit administrative operations. Possession of Auth grants access; never expose this capability to untrusted plugins or dispatch it from browser routes. The host must authorize its admin caller. Request authentication is not an administrative authorization grant.
func (AdminService) CompleteStepUp ¶
func (s AdminService) CompleteStepUp(ctx context.Context, method AuditMethod, verify func(storage.Tx, storage.User, storage.Session) (AssuranceLevel, error)) (IssuedSession, error)
CompleteStepUp is a trusted host/plugin capability, never a browser DTO. verify must verify/consume fresh proof bound to this user, session and epoch inside tx and return the assurance actually proven. MultiFactor requires two independent factors (or a user-verified multi-factor authenticator); a method name or two proofs of the same factor is insufficient. Stale existing evidence cannot be counted. Proof consumption, old-bearer revocation and issuance commit together. All returned credentials must be discarded on error. An impersonation session cannot step up: forbidden.
func (AdminService) CreateUser ¶
func (s AdminService) CreateUser(ctx context.Context, input CreateUser) (User, error)
CreateUser is the administrative import contract, not browser registration. It remains unavailable until transactional identity storage is implemented.
func (AdminService) DeleteUser ¶
func (s AdminService) DeleteUser(ctx context.Context, userID string) error
DeleteUser is the administrative deletion for operator-driven removal, such as a data-subject request. The host authorizes its caller; no session is involved. It performs the same transactional cascade, mail withdrawal and audit event as DeleteCurrent, attributed to the host or to the administrator of an Operator context. A suspended account can be deleted. Like RevokeAllSessions, an unknown user is reported as unauthenticated.
func (AdminService) Impersonate ¶
func (s AdminService) Impersonate(ctx context.Context, targetID string, duration time.Duration) (IssuedSession, error)
Impersonate starts an impersonation of targetID by the administrator whose validated session ctx carries (a request behind RequireSession, or from Sessions().Authenticate), and returns a new session for the target. It requires Config.Impersonation. The operator's session must be live, not suspended, not itself an impersonation, and satisfy the policy's assurance and recency; the target must exist, not be the operator and not be suspended; and Authorize must allow the pair. The operator's session must also prove at least the assurance the target's AssurancePolicy requires, so impersonation never bypasses the target's MFA policy, and the new session carries the operator's assurance, never more.
The session lasts duration (zero is the policy's MaxDuration, which is also the upper bound) and never outlives the operator's session. It is the target's session in every ordinary respect, except that each use revalidates the operator and Authorize first, every event it causes is attributed to the operator with the target as subject, and it can never perform an operation that requires recent authentication, step up, or sign the target out everywhere: those are forbidden. Neither the operator's nor the target's own sessions change. Records admin.impersonation_start, whose actor session is the operator's own and whose session is the impersonation session. A denial by Authorize is recorded as a forbidden failure on that operation.
func (AdminService) IssueSession ¶
func (s AdminService) IssueSession(ctx context.Context, userID string, method AuditMethod) (IssuedSession, error)
IssueSession is a host-only authentication capability. The host must have just authenticated this user and names how (MethodPassword, MethodMagicLink, OAuthMethod or a host identifier) so the audit event records the method. Never dispatch it from a user-ID browser input. The impersonation method is reserved for Impersonate and is a bad request here.
func (AdminService) Operator ¶
func (s AdminService) Operator(ctx context.Context, p OperatorPolicy) (context.Context, error)
Operator binds the administrative calls made with the returned context to the administrator whose validated session ctx carries, for example a request behind RequireSession. The session is checked now and again at the start of every administrative call: it must be live, not suspended, satisfy the policy's assurance and recency, and pass Authorize. The events of those calls are attributed to that user and session instead of the host. The operator cannot suspend their own account. Only one account can be locked per transaction, so the recheck commits before the target account is locked; revoke an administrator's sessions to stop calls already admitted.
func (AdminService) Reinstate ¶
func (s AdminService) Reinstate(ctx context.Context, userID string) error
Reinstate lifts a suspension. It restores nothing the suspension revoked: the user signs in again with any credential that still exists, and API keys that were neither revoked nor expired work again. Reinstating an active account succeeds without change of state. Records admin.user_reinstate.
func (AdminService) RevokeAllSessions ¶
func (s AdminService) RevokeAllSessions(ctx context.Context, userID string) error
RevokeAllSessions advances the account's security epoch, revoking every session and outstanding proof without suspending it. Records admin.sessions_revoke. An unknown user is unauthenticated.
func (AdminService) RevokeSession ¶
func (s AdminService) RevokeSession(ctx context.Context, userID, sessionID string) error
RevokeSession revokes one of an account's sessions by its public ID. Revoking an already revoked session succeeds; a session the account does not own is unauthenticated, like an unknown account. Records admin.session_revoke with the session.
func (AdminService) Sessions ¶
func (s AdminService) Sessions(ctx context.Context, userID, afterID string, limit int) ([]Session, error)
Sessions lists at most limit (1..100) of an account's active sessions in ID order after afterID, for an administrator deciding what to revoke.
func (AdminService) Suspend ¶
func (s AdminService) Suspend(ctx context.Context, userID string) error
Suspend withdraws every form of access from an account until Reinstate. In one transaction it marks the account suspended and advances its security epoch, which revokes every session (including pending MFA sessions) and every outstanding verification, reset, email-change and magic-link proof. Afterwards no supported method can authenticate the account: password, magic link, OAuth, passkey, TOTP and recovery step-up, host IssueSession, and API keys through WithCredential are all refused, and reset, verification and magic-link requests send nothing. API keys are blocked, not revoked. Suspending a suspended account succeeds, keeps the original time and revokes again. Records admin.user_suspend.
func (AdminService) VerifyAndIssueSession ¶
func (s AdminService) VerifyAndIssueSession(ctx context.Context, userID string, method AuditMethod, verify func(storage.Tx, storage.User) (AssuranceLevel, error)) (IssuedSession, error)
VerifyAndIssueSession is a trusted authentication plugin capability. userID only selects the account to lock; verify must authenticate that account using fresh proof and consume the proof in tx. The proof and session commit together. Never expose a callback that accepts browser claims as verified assurance.
type AssuranceLevel ¶
type AssuranceLevel int
AssuranceLevel describes verified evidence, not a claim about NIST compliance.
const ( SingleFactor AssuranceLevel = 1 MultiFactor AssuranceLevel = 2 )
type AssurancePolicy ¶
AssurancePolicy reads factor enrollment under the user's transaction lock. It must return a valid minimum on every call; errors fail closed. It must not perform network I/O or retain tx. Nil preserves single-factor deployments.
type AssuranceRequirement ¶
type AssuranceRequirement struct {
Level AssuranceLevel
MaxAge time.Duration
}
AssuranceRequirement is checked against authoritative state within a mutation. MaxAge zero imposes no age limit; positive ages are exclusive upper bounds.
type AuditEvent ¶
type AuditEvent = storage.AuditEvent
AuditEvent and AuditQuery are the storage records: identifiers, timestamps and closed vocabularies only. See docs/audit-events.md for the field contract.
type AuditFailure ¶
type AuditFailure struct {
Operation plugin.Operation
Reason AuditReason
Method AuditMethod
SubjectUserID string
AsHost bool
}
AuditFailure describes a rejected attempt for RecordFailure. Method names the sign-in method when the attempt was a sign-in; SubjectUserID names the account the attempt targeted when the caller established it. AsHost attributes the failure to the host, as a refused administrative or provisioning call made with WithAdministration is, ignoring any session or credential in the context.
type AuditMethod ¶
type AuditMethod string
AuditMethod names how a user authenticated on sign-in events. Use the constants, OAuthMethod, or a host-defined identifier matching ^[a-z][a-z0-9_.-]{0,79}$. Events that are not sign-ins carry no method.
const ( MethodPassword AuditMethod = "password" MethodMagicLink AuditMethod = "magic_link" )
const MethodImpersonation AuditMethod = "impersonation"
MethodImpersonation is the public method of an impersonation session and the audit method of the events recorded through one. It and every method under "impersonation." are reserved: host and plugin issuance reject them.
func OAuthMethod ¶
func OAuthMethod(providerID string) AuditMethod
OAuthMethod names a sign-in through the configured provider identifier, so events distinguish providers ("oauth.google", "oauth.github").
type AuditQuery ¶
type AuditQuery = storage.AuditQuery
type AuditReason ¶
type AuditReason string
AuditReason is the closed failure vocabulary. Reasons describe why a presented credential or proof was rejected; they never carry input values.
const ( ReasonInvalidCredentials AuditReason = "invalid_credentials" // password mismatch or malformed password ReasonUnknownIdentity AuditReason = "unknown_identity" // no account, or no password for it ReasonEmailUnverified AuditReason = "email_unverified" // a correct password for an unverified account ReasonInvalidProof AuditReason = "invalid_proof" // unknown, expired, consumed or mismatched proof or provider transaction )
const ( ReasonAccountSuspended AuditReason = "account_suspended" ReasonForbidden AuditReason = "forbidden" )
ReasonAccountSuspended records an otherwise valid authentication, proof or credential refused because an administrator suspended the account. ReasonForbidden records an administrator whose own authorization failed.
type AuditService ¶
type AuditService struct {
// contains filtered or unexported fields
}
AuditService is a host-only capability over the durable trail. Possession of Auth grants it; never dispatch it from browser routes without the host's own administrative authorization. Events contain no credential material.
func (AuditService) Events ¶
func (s AuditService) Events(ctx context.Context, q AuditQuery) ([]AuditEvent, error)
Events lists events in sequence order after the query cursor. Pages are current views; use the final Sequence as the next AfterSequence.
func (AuditService) Prune ¶
Prune deletes at most limit events recorded before the cutoff and returns the count. The library never prunes on its own; the host schedules retention.
func (AuditService) RecordFailure ¶
func (s AuditService) RecordFailure(ctx context.Context, f AuditFailure) error
RecordFailure records a rejected attempt from trusted host or plugin code, attributing actor and client address from ctx. The event is durable in its own transaction; a storage failure is returned after being logged with the operation and reason only.
type Auth ¶
type Auth struct {
// contains filtered or unexported fields
}
Auth is safe for concurrent use. It owns its cancellation scope and admitted work, but never closes host-owned storage, loggers or secret providers.
func New ¶
New validates and freezes configuration without starting workers or changing schema. ctx is the instance lifetime, not an individual HTTP request context. Dependency implementations must honor cancellation and must not panic.
func (*Auth) Abuse ¶
func (a *Auth) Abuse() AbuseService
func (*Auth) Admin ¶
func (a *Auth) Admin() AdminService
func (*Auth) Audit ¶
func (a *Auth) Audit() AuditService
func (*Auth) AuthenticateRequest ¶
AuthenticateRequest attaches the session that r's session cookie carries, verified against authoritative storage, as RequireSession does, without requiring one: with no cookie it returns r unchanged. A malformed, duplicated, expired or revoked cookie is an error. It is for plugin endpoints outside Handler that act differently for signed-in browsers; it applies no origin or CSRF policy.
func (*Auth) Close ¶
Close refuses new work, cancels admitted work, and waits for it to finish. A deadline only bounds this wait; another Close can continue waiting. Closing is idempotent. Future durable workers must requeue or drain before returning.
func (*Auth) Contract ¶
Contract returns the description validated at startup for this instance's configured core and plugin endpoints. Treat the result as read-only.
func (*Auth) Credentials ¶
func (a *Auth) Credentials() CredentialsService
func (*Auth) Deployment ¶
func (a *Auth) Deployment() Deployment
Deployment returns the instance's validated topology.
func (*Auth) EndImpersonation ¶
EndImpersonation is the browser form of Sessions().EndImpersonation. It revokes the impersonation session in the session cookie, if it still authenticates, and restores the operator's own session from the cookie StartImpersonation saved; if that session has meanwhile ended, the browser is signed out instead. It also recovers a browser whose impersonation already expired or was revoked. A live session that is not an impersonation is a bad request and no cookie changes. The host route owns CSRF protection.
func (*Auth) Handler ¶
Handler serves the authentication API. Mount with http.StripPrefix. Session verification uses authoritative storage; GET requests never renew sessions.
func (*Auth) Passwords ¶
func (a *Auth) Passwords() PasswordsService
func (*Auth) ProtocolRequest ¶
ProtocolRequest validates the transport of a request that a plugin serves outside Handler at origin, which must satisfy ServesOrigin: the forwarding headers from trusted proxies, the public origin and, in Development, the loopback peer, exactly as Handler does. It returns the request with the client address attached, so audit events recorded under its context name it, and the address for abuse budgets. It applies no origin, CSRF, body or cookie policy: the caller owns those.
func (*Auth) RequireSession ¶
RequireSession checks shared service authorization. It does not apply the auth API's host/body/CSRF policies to host application routes; those are owned by the host. Session cookies are verified against authoritative storage.
func (*Auth) Retention ¶
func (a *Auth) Retention() RetentionService
func (*Auth) SafeRedirect ¶
SafeRedirect returns an absolute URL under BaseURL. Redirects deliberately permit only local absolute paths, never a caller-supplied external origin. Host and forwarding headers cannot affect the destination.
func (*Auth) ServesOrigin ¶
ServesOrigin reports whether origin is a canonical origin that receives the session cookie: BaseURL's origin, or with a cookie domain (T2) an origin of the same scheme whose host is inside it.
func (*Auth) Sessions ¶
func (a *Auth) Sessions() SessionsService
func (*Auth) SetSessionCookie ¶
func (a *Auth) SetSessionCookie(w http.ResponseWriter, issued IssuedSession) error
SetSessionCookie delivers a committed issuance result using the configured browser policy. Host authentication flows must not serialize Token themselves.
func (*Auth) StartImpersonation ¶
func (a *Auth) StartImpersonation(w http.ResponseWriter, r *http.Request, targetID string, duration time.Duration) (IssuedSession, error)
StartImpersonation is the browser form of Impersonate for a host's own administrative route. r must carry the operator's validated session from the session cookie (behind RequireSession). On success the operator's bearer is moved to a separate HttpOnly cookie and the session cookie carries the impersonation session, so EndImpersonation can restore the operator. The host route owns CSRF protection and must authorize the request like any other administrative action.
func (*Auth) Users ¶
func (a *Auth) Users() UsersService
func (*Auth) WithAdministration ¶
func (a *Auth) WithAdministration(ctx context.Context, operation plugin.Operation, userID string, fn func(storage.Tx, storage.User) error) error
WithAdministration runs a trusted administrative mutation against userID's account under that account's lock. It is how plugins add administrative capabilities with the core's attribution: the host by default, or the administrator of an Operator context, rechecked first. A non-empty operation records a success event whose subject is the account. Suspension does not block administration. An unknown account is unauthenticated. fn must not perform network I/O or retain the transaction. Possession of Auth is a trusted host capability; never accept userID from a caller the host has not authorized to administer it.
func (*Auth) WithAdministrationTx ¶
func (a *Auth) WithAdministrationTx(ctx context.Context, operation plugin.Operation, fn func(storage.Tx) error) error
WithAdministrationTx runs trusted administrative work that concerns no single account, such as a directory's group records, with the attribution of WithAdministration: the host, or the administrator of an Operator context, rechecked first. No account is locked, so fn must not call storage methods that require one. A non-empty operation records a success event without a subject. fn must not perform network I/O or retain the transaction.
func (*Auth) WithAssurance ¶
func (a *Auth) WithAssurance(ctx context.Context, op plugin.Operation, r AssuranceRequirement, fn func(storage.Tx, storage.User, storage.Session) error) error
WithAssurance runs a trusted mutation and its assurance check atomically.
func (*Auth) WithCredential ¶
func (a *Auth) WithCredential(ctx context.Context, operation plugin.Operation, credential AuditMethod, owner func(storage.Tx) (string, error), fn func(storage.Tx, storage.User) error) error
WithCredential runs trusted work authenticated by a non-session credential, such as an API key, that acts for one account. It is a distinct authentication mode: any session in ctx is ignored, and the audit event is attributed to the owning account as a user actor with no session, naming credential (for example "api_key.<id>") as its method. owner reads, without locking, the account the presented credential claims; the core then locks that account and calls fn, which must verify the credential and every restriction on it under that lock before acting. A suspended account is refused before fn runs, with an account_suspended failure event. An empty operation records no event. fn must not perform network I/O or retain the transaction. Possession of Auth is a trusted host/plugin capability; never accept an owner or credential identifier from request input as proof.
func (*Auth) WithNewAccount ¶
func (a *Auth) WithNewAccount(ctx context.Context, operation plugin.Operation, input CreateUser, fn func(storage.Tx, storage.User) error) (User, error)
WithNewAccount creates an account for trusted provisioning code, such as a directory that proved control of the address's domain, and runs fn under the new account's lock in the same transaction. The account has no password or linked identity; its address is marked verified when input.EmailVerified, which is the caller's vouching for it. Attribution is administrative, as for WithAdministration: the host, or the administrator of an Operator context, rechecked first. A non-empty operation records a success event whose subject is the new account, and the plugin hooks see it. An address another account has, verified or not, is refused without change (IsEmailTaken): an existing account is never adopted or merged here. fn may be nil; it must not perform network I/O or retain the transaction. Possession of Auth is a trusted capability; never create accounts from input the host has not authorized.
func (*Auth) WithRecentSession ¶
func (a *Auth) WithRecentSession(ctx context.Context, operation plugin.Operation, fn func(storage.Tx, storage.User, storage.Session) error) error
WithRecentSession runs a trusted plugin mutation under the actor's owner lock. It revalidates the live session and five-minute authentication age in the same transaction as fn and plugin hooks. fn must not perform network I/O or retain the transaction. Possession of Auth is a trusted host/plugin capability.
type AuthenticationState ¶
type AuthenticationState string
AuthenticationState deliberately distinguishes a pending MFA flow from a usable session. Unknown values must fail closed just like Pending.
const ( Unauthenticated AuthenticationState = "unauthenticated" Pending AuthenticationState = "pending" Authenticated AuthenticationState = "authenticated" )
type Clock ¶
Clock implementations must be safe for concurrent use. Production defaults to the system clock. Tests may inject a clock without sleeping.
type Code ¶
type Code string
Code is a stable machine-readable error category. New codes are additive.
const ( CodeRateLimited Code = "rate_limited" CodeOverloaded Code = "overloaded" CodeInvalidConfiguration Code = "invalid_configuration" CodeUnauthenticated Code = "unauthenticated" CodeForbidden Code = "forbidden" CodeAssuranceRequired Code = "assurance_required" CodeRecentAuthenticationRequired Code = "recent_authentication_required" CodeClosed Code = "closed" CodeBadRequest Code = "bad_request" CodeNotFound Code = "not_found" CodeMethodNotAllowed Code = "method_not_allowed" CodeBodyTooLarge Code = "body_too_large" CodeUnsupportedMediaType Code = "unsupported_media_type" )
type Config ¶
type Config struct {
AssurancePolicy AssurancePolicy
SensitiveAssurance AssuranceLevel // zero defaults to SingleFactor
Plugins []plugin.Definition
Registration RegistrationConfig
Abuse AbuseConfig
BaseURL string
Secret SecretSource
TrustedOrigins []string
TrustedProxies []string
Cookie CookieConfig
Session SessionConfig
Development bool // Explicit HTTP loopback exception; never for deployment.
Clock Clock
Random io.Reader // Test override, permitted only in Development mode.
Logger *slog.Logger
Store storage.Store // Optional; session operations fail closed without storage.
Startup StartupChecker
Protector Protector
// Impersonation enables Admin().Impersonate; nil (the default) disables
// it. See docs/impersonation.md.
Impersonation *ImpersonationPolicy
}
Config is copied and validated by New. Mutating its slices afterwards cannot alter an instance. Injected interfaces remain host-owned and must be safe for concurrent use. No request-specific state belongs in Config.
func (Config) MarshalJSON ¶
type CookieConfig ¶
CookieConfig is optional; zero values select Secure, HttpOnly, Lax, Path=/ and a host-only __Host-sigil_session cookie. Insecure flags aren't exposed.
type CreateUser ¶
type Credentials ¶
Credentials contains untrusted input. Passwords are never normalized.
type CredentialsService ¶
type CredentialsService struct {
// contains filtered or unexported fields
}
func (CredentialsService) ChangePassword ¶
func (s CredentialsService) ChangePassword(ctx context.Context, ip netip.Addr, current, password Secret) error
ChangePassword requires a verified, recently authenticated actor and the current password. All proof bindings are rechecked after hashing, under the user lock. Success invalidates every session (including the caller) and pending challenge.
func (CredentialsService) ConfirmEmailChange ¶
func (s CredentialsService) ConfirmEmailChange(ctx context.Context, ip netip.Addr, token Secret) error
ConfirmEmailChange proves control of the pending address. Changing and verifying the address, consuming the proof and invalidating all sessions/challenges commit together. Sign in again after success; this method never issues a session.
func (CredentialsService) Register ¶
func (s CredentialsService) Register(ctx context.Context, ip netip.Addr, input Credentials) error
Register returns the same success for a new and an existing identity, and never issues a session. User, password, challenge and mail commit together. ip must come from the host's trusted client-IP policy; HTTP derives it itself.
func (CredentialsService) RequestEmailChange ¶
func (s CredentialsService) RequestEmailChange(ctx context.Context, ip netip.Addr, target string) error
RequestEmailChange requires a verified account and authentication less than five minutes old, rechecked under the user lock. The old address remains authoritative until confirmation. Existing targets receive the same accepted result and no mail.
func (CredentialsService) RequestPasswordReset ¶
func (s CredentialsService) RequestPasswordReset(ctx context.Context, ip netip.Addr, target string) error
RequestPasswordReset accepts all canonical addresses uniformly. Only verified accounts with a password receive a durable, fifteen-minute recovery proof.
func (CredentialsService) ResendVerification ¶
func (s CredentialsService) ResendVerification(ctx context.Context, ip netip.Addr, target string) error
ResendVerification accepts existing, missing and already verified addresses uniformly. Only an unverified current identity receives a new proof; issuing a resend does not revoke older, still valid verification links.
func (CredentialsService) ResetPassword ¶
func (s CredentialsService) ResetPassword(ctx context.Context, ip netip.Addr, token, password Secret) error
ResetPassword consumes a recovery proof, replaces the password and invalidates all sessions and outstanding challenges in one transaction. It issues no session.
func (CredentialsService) SignIn ¶
func (s CredentialsService) SignIn(ctx context.Context, ip netip.Addr, input Credentials) (IssuedSession, error)
SignIn verifies outside the database transaction, then revalidates all proof bindings and issues under one user lock. Email verification is required; unverified accounts receive the same failure as invalid credentials.
func (CredentialsService) VerifyEmail ¶
VerifyEmail consumes the registration proof and verifies its bound address. It never issues or renews a session. The host must require explicit confirmation.
type Deployment ¶
type Deployment struct {
// BaseURL is the canonical origin of Handler.
BaseURL string
// CookieDomain is the session cookie's Domain attribute, empty for a
// host-only cookie (T1).
CookieDomain string
// TrustedOrigins are the exact origins whose pages may call Handler.
TrustedOrigins []string
Development bool
}
Deployment is the validated browser topology, for plugins that serve endpoints outside Handler and must agree with the core's cookie and origin policy. It is a copy; changing it changes nothing.
type Error ¶
type Error struct {
Code Code `json:"code"`
Message string `json:"message"`
Field string `json:"field,omitempty"`
}
Error contains only library-controlled diagnostics, never dependency errors, request values or credentials. Field identifies an invalid configuration field.
type ImpersonationPolicy ¶
type ImpersonationPolicy struct {
Assurance AssuranceRequirement
MaxDuration time.Duration
Authorize func(ctx context.Context, operator, target User) error
}
ImpersonationPolicy enables impersonation (Config.Impersonation); without one, Impersonate is unavailable and any stored impersonation session is refused. Assurance is what the operator's own session must prove to start: MaxAge must be positive, and Level is raised to Config.SensitiveAssurance. MaxDuration bounds every impersonation session (zero is 15 minutes, at most one hour). Authorize is the host's privilege check and target exclusion: it runs when impersonation starts and again, with the freshly revalidated operator, before every request the impersonation session makes. A non-nil error denies, except ErrUnavailable, which is passed through. Authorize must be safe for concurrent use and must refuse any target the operator must not act as, such as another administrator.
type IssuedSession ¶
type IssuedSession struct {
View SessionView `json:"view"`
Token Secret `json:"-"`
}
IssuedSession exposes the bearer only through Secret.Reveal. It must be sent to its intended client only after the issuing transaction has committed.
type LocalMailSink ¶
type LocalMailSink struct {
// contains filtered or unexported fields
}
LocalMailSink is a bounded, in-memory DEVELOPMENT sender. It has no HTTP route, disk writes or automatic logging. Drain explicitly transfers sensitive previews to host code and clears retained messages. Full sinks fail so work is retried.
func NewLocalMailSink ¶
func NewLocalMailSink(capacity int) (*LocalMailSink, error)
func (*LocalMailSink) Drain ¶
func (s *LocalMailSink) Drain() []Mail
type Mail ¶
Mail contains rendered, sensitive content. Reveal only inside the sender or an explicitly host-controlled local preview. ID is a provider idempotency key.
type MailDelivery ¶
type MailDelivery struct {
// contains filtered or unexported fields
}
func NewMailDelivery ¶
func NewMailDelivery(store storage.DeliveryStore, protector Protector, sender MailSender) (*MailDelivery, error)
func (*MailDelivery) DispatchOne ¶
func (d *MailDelivery) DispatchOne(ctx context.Context) (bool, error)
DispatchOne synchronously claims and attempts one message, with a 30-second send deadline (shorter than the lease). The host schedules calls and cleanup. A failed send is durably rescheduled and returns ErrDelivery, with no provider text. A crash after provider acceptance can cause duplicate delivery.
func (*MailDelivery) Enqueue ¶
func (d *MailDelivery) Enqueue(ctx context.Context, tx storage.Tx, id string, template MailTemplate, ttl time.Duration) error
Enqueue must be called inside Store.WithinTx. Use a fresh random operation ID and persist it with the business operation. A conflict aborts the transaction; an ambiguous commit must be reconciled, never retried with a new operation ID.
func (*MailDelivery) Rotate ¶
Rotate re-encrypts up to limit live payloads sealed under a key other than the protector's active key, scanning IDs after cursor. Run it from a trusted process after every replica holds the new keyring, repeating from "" until a full pass reports nothing rewrapped and nothing unreadable; only then retire the old key. Replacement is compare-and-swap, so a concurrent send or another pass is never overwritten. Plaintext exists only in this process's memory.
type MailSender ¶
MailSender must honor cancellation; success means provider acceptance, not inbox receipt. Providers should deduplicate Mail.ID whenever supported.
type MailTemplate ¶
MailTemplate renders before enqueue, freezing template content across retries. Hosts own URLs, escaping (use html/template), localization and sender address.
type OperatorPolicy ¶
type OperatorPolicy struct {
Assurance AssuranceRequirement
Authorize func(context.Context, User) error
}
OperatorPolicy is what an administrator's own session must prove before administrative calls made with an Operator context proceed. Assurance must name a positive MaxAge; its Level is raised to the configured sensitive assurance. Authorize is the host's privilege check (for example an admin role) and runs on every call with the freshly revalidated operator; a non-nil error denies the call as forbidden, except ErrUnavailable, which is passed through.
type PasswordVerification ¶
PasswordVerification contains no plaintext. Upgrade is nonempty only after a matching historical verifier, and must be persisted with a credential revision check under the user lock. This result alone never authorizes session issuance.
type PasswordsService ¶
type PasswordsService struct {
// contains filtered or unexported fields
}
PasswordsService is a host-only cryptographic primitive, not a sign-in flow. Network-facing callers must charge Abuse().Do with expensive=false first; these methods reserve the shared expensive slot themselves, with no queue. Do not invoke them inside an expensive=true callback.
func (PasswordsService) Hash ¶
Hash validates new-password policy and returns a randomly salted PHC verifier.
func (PasswordsService) Verify ¶
func (s PasswordsService) Verify(ctx context.Context, password Secret, verifier storage.Material) (PasswordVerification, error)
Verify accepts only bounded Argon2id v19 PHC records. Mismatch returns an empty result and nil error; malformed/unsupported records return ErrBadRequest. Matching older parameters are rehashed within the same admission slot.
type ProtectionBinding ¶
type ProtectionBinding struct{ Purpose, RecordID string }
ProtectionBinding must be authenticated along with the envelope. A ciphertext for one purpose or record must never decrypt under another binding.
type Protector ¶
type Protector interface {
Seal(context.Context, ProtectionBinding, Secret) ([]byte, error)
Open(context.Context, ProtectionBinding, []byte) (Secret, error)
}
Protector is the host-injectable recoverable-secret boundary. Implementations must use versioned authenticated encryption, key IDs and binding metadata; fail closed on tampering/unknown keys; and respect cancellation. AUTH-016 supplies the AES-256-GCM envelope; the Rotator extension and MailDelivery.Rotate (AUTH-031) re-encrypt live ciphertext under a new key. Ciphertext is internal persistence material, never a public response DTO.
func NewAESProtector ¶
NewAESProtector copies a keyring of raw 32-byte AES keys. Key IDs are public, immutable identifiers; keep old keys while their ciphertext remains live. This constructor starts no workers and never derives keys from passwords.
type RegistrationConfig ¶
type RegistrationConfig struct {
Delivery *MailDelivery
RenderVerification func(context.Context, string, Secret) (Mail, error)
// RenderEmailChange optionally enables pending address changes. It has the
// same rendering-only contract and must link to the change confirmation flow.
RenderEmailChange func(context.Context, string, Secret) (Mail, error)
// RenderPasswordReset optionally enables password recovery, using the same rendering-only contract.
RenderPasswordReset func(context.Context, string, Secret) (Mail, error)
}
RegistrationConfig enables registration with durable verification mail. RenderVerification must be concurrency-safe, honor cancellation, and only render content (no sending or other external side effects). The host owns safe confirmation URLs and escaping. Sigil sets the canonical recipient. Delivery's dispatcher must use the same store as Config.Store.
type RequestContext ¶
type RequestContext struct {
State AuthenticationState `json:"state"`
User User `json:"user"`
Session Session `json:"session"`
}
RequestContext is a credential-free snapshot of validated authentication. It is not an input capability: constructing one does not authorize a call.
func RequestFromContext ¶
func RequestFromContext(ctx context.Context) RequestContext
RequestFromContext returns a value copy. Missing authentication is explicit.
type RetentionService ¶
type RetentionService struct {
// contains filtered or unexported fields
}
RetentionService is the host-only capability over expired-row cleanup. The library never prunes on its own; the host schedules it alongside MailDelivery.Cleanup, Audit().Prune and the plugin pruners.
func (RetentionService) PruneExpired ¶
func (s RetentionService) PruneExpired(ctx context.Context, before time.Time, limit int) (Pruned, error)
PruneExpired deletes from each core table at most limit (1..1000) rows that expired at or before the cutoff (clamped to database time, so live rows are never removed) and returns the counts. Repeat while any count equals limit. A store without the extension is unavailable.
type RetryError ¶
RetryError exposes a bounded retry hint without identity or storage diagnostics.
func (*RetryError) Error ¶
func (e *RetryError) Error() string
func (*RetryError) Unwrap ¶
func (e *RetryError) Unwrap() error
type Rotation ¶
type Rotation struct {
Next string // cursor for the next call; empty once the scan reached the end
Visited int
Rewrapped int
Unreadable int // malformed envelopes or keys missing from the keyring; retire nothing while nonzero
}
Rotation reports one re-encryption pass over live outbox payloads.
type Rotator ¶
Rotator is an optional Protector extension for operational key rotation. ActiveKeyID names the key new ciphertext uses. KeyID names the key an existing envelope was sealed under without decrypting it, whether or not that key is still in the keyring, so rotation can find ciphertext that depends on a key scheduled for retirement; a malformed envelope is ErrProtection.
type Secret ¶
type Secret struct {
// contains filtered or unexported fields
}
Secret prevents accidental disclosure through formatting, JSON and slog. Reveal is an explicit trust boundary; callers must not log its result. Go cannot guarantee erasure of strings or protect against in-process code.
func (Secret) MarshalJSON ¶
type SecretSource ¶
SecretSource resolves deployment key material at startup, respecting ctx. It must return at least 32 random bytes (encoded text is allowed). Length validation cannot establish entropy. Sources are host-owned and not closed.
func SecretFromEnv ¶
func SecretFromEnv(name string) SecretSource
SecretFromEnv reads the environment at construction time, not on each request.
type Session ¶
type Session struct {
Assurance AssuranceLevel `json:"assurance"`
Method string `json:"method"`
ID string `json:"id"`
UserID string `json:"userId"`
State AuthenticationState `json:"state"`
CreatedAt time.Time `json:"createdAt"`
AuthenticatedAt time.Time `json:"authenticatedAt"`
ExpiresAt time.Time `json:"expiresAt"`
}
Session is a public view. ID is a non-bearer identifier; no raw token or digest may be assigned to it. AuthenticatedAt is the last completed authentication, not session renewal. Pending timestamps describe the first-factor proof only.
type SessionConfig ¶
type SessionView ¶
type SessionsService ¶
type SessionsService struct {
// contains filtered or unexported fields
}
func (SessionsService) Authenticate ¶
Authenticate validates an opaque bearer against authoritative storage without renewing it. The resulting context is instance-bound; service calls revalidate it so a saved context cannot bypass subsequent revocation.
func (SessionsService) Authentication ¶
func (s SessionsService) Authentication(ctx context.Context) (SessionView, error)
Authentication returns the live flow state, including pending. It grants no ordinary access. Factor routes may use it to render a challenge.
func (SessionsService) Current ¶
func (s SessionsService) Current(ctx context.Context) (SessionView, error)
func (SessionsService) EndImpersonation ¶
func (s SessionsService) EndImpersonation(ctx context.Context) error
EndImpersonation revokes the impersonation session ctx carries. The operator's and the target's own sessions are untouched. A session that is not an impersonation is a bad request. Records admin.impersonation_end, attributed like every event of the impersonation session. The operator can also end it from their console with Admin().RevokeSession.
func (SessionsService) List ¶
List returns at most 100 active, owned sessions in ID order. Use the final ID as afterID for the next page. The empty cursor starts a new listing.
func (SessionsService) Renew ¶
func (s SessionsService) Renew(ctx context.Context) (SessionView, error)
Renew extends idle expiry only at/after RenewAfter. It preserves the bearer, absolute deadline and authentication time, and never renews on read requests.
func (SessionsService) RequireAssurance ¶
func (s SessionsService) RequireAssurance(ctx context.Context, r AssuranceRequirement) error
RequireAssurance is a read-only check. Mutations must use WithAssurance to avoid revocation, enrollment and check/use races.
func (SessionsService) RequireRecent ¶
RequireRecent authenticates from storage, then requires age strictly below maxAge. Renewal never refreshes this evidence. Future sensitive mutations must apply this predicate inside their own transaction to avoid a check/use race.
func (SessionsService) RevokeAll ¶
func (s SessionsService) RevokeAll(ctx context.Context) error
RevokeAll invalidates all existing sessions and challenges through the user's security epoch. Issuance serialized after this operation belongs to the new epoch. An impersonation session cannot sign its target out everywhere: forbidden.
func (SessionsService) RevokeCurrent ¶
func (s SessionsService) RevokeCurrent(ctx context.Context) error
type StartupChecker ¶
StartupChecker checks connectivity/schema compatibility without writes or migrations. The host owns the dependency and its shutdown. AUTH-008/010 will connect this contract to the storage adapter.
type User ¶
type User struct {
ID string `json:"id"`
Email string `json:"email"`
EmailVerified bool `json:"emailVerified"`
CreatedAt time.Time `json:"createdAt"`
}
User is a public identity view, never a credential persistence record.
type UsersService ¶
type UsersService struct {
// contains filtered or unexported fields
}
UsersService and SessionsService enforce actor authorization for both HTTP and direct calls. They never accept caller-asserted actors or admin flags.
func (UsersService) DeleteCurrent ¶
func (s UsersService) DeleteCurrent(ctx context.Context) error
DeleteCurrent deletes the signed-in user's account. It requires an active session authenticated strictly less than five minutes ago, rechecked under the user lock in the deleting transaction. The user row and everything that cascades from it (password, linked identities, sessions including the caller's, pending proofs and cascading plugin rows) go in one transaction with the account.delete audit event; queued proof mail addressed to the account is withdrawn. Afterwards no supported method can authenticate the account, the address is free to register again, and the trail keeps the account's events until the host prunes them. Deletion is final.
Source Files
¶
- abuse.go
- assurance.go
- audit.go
- config.go
- contract.go
- credentials.go
- deletion.go
- delivery.go
- doc.go
- email.go
- errors.go
- http.go
- http_body.go
- http_cookie.go
- http_credentials.go
- http_csrf.go
- http_email.go
- http_password.go
- http_policy.go
- impersonation.go
- models.go
- password_recovery.go
- passwords.go
- plugins.go
- protector.go
- protocol.go
- provisioning.go
- secrets.go
- services.go
- sessions.go
- sigil.go
- suspension.go
- version.go
Directories
¶
| Path | Synopsis |
|---|---|
|
Package cli implements the operator command set behind cmd/sigil: contract export, migration status, planning, apply and SQL export, deployment diagnostics and bounded expired-row cleanup.
|
Package cli implements the operator command set behind cmd/sigil: contract export, migration status, planning, apply and SQL export, deployment diagnostics and bounded expired-row cleanup. |
|
cmd
|
|
|
sigil
command
Command sigil is the operator tool for this repository: contract export, migrations, diagnostics and cleanup over the core and the in-repo plugins.
|
Command sigil is the operator tool for this repository: contract export, migrations, diagnostics and cleanup over the core and the in-repo plugins. |
|
Package contract describes the HTTP API as data: endpoint metadata, JSON schemas, the safe error catalogue and a deterministic OpenAPI 3.1 export.
|
Package contract describes the HTTP API as data: endpoint metadata, JSON schemas, the safe error catalogue and a deterministic OpenAPI 3.1 export. |
|
examples
|
|
|
authserver
command
Command authserver runs a disposable host that operates an OAuth 2.0 authorization server and OpenID Connect provider with plugin/authserver, together with a demo relying party on a second origin.
|
Command authserver runs a disposable host that operates an OAuth 2.0 authorization server and OpenID Connect provider with plugin/authserver, together with a demo relying party on a second origin. |
|
browser
command
Command browser runs the local password authentication journey.
|
Command browser runs the local password authentication journey. |
|
browser/testdb
command
Command testdb removes only a uniquely named browser, client or react test schema.
|
Command testdb removes only a uniquely named browser, client or react test schema. |
|
client
command
Command client hosts the framework-neutral TypeScript client against the real Go server: the shared HTTPS loopback host (core credentials, the magic-link plugin, the OAuth plugin bound to a built-in mock OIDC provider and a local mail preview) plus a page that talks to the API only through @sigil-auth/client.
|
Command client hosts the framework-neutral TypeScript client against the real Go server: the shared HTTPS loopback host (core credentials, the magic-link plugin, the OAuth plugin bound to a built-in mock OIDC provider and a local mail preview) plus a page that talks to the API only through @sigil-auth/client. |
|
internal/loopback
Package loopback is the HTTPS loopback host shared by the browser examples that drive the TypeScript packages against the real Go server: core credentials with verification and reset mail, the magic-link plugin, the OAuth plugin bound to a built-in mock OIDC provider, and a development mail preview, served under a throwaway certificate on a loopback address.
|
Package loopback is the HTTPS loopback host shared by the browser examples that drive the TypeScript packages against the real Go server: core credentials with verification and reset mail, the magic-link plugin, the OAuth plugin bound to a built-in mock OIDC provider, and a development mail preview, served under a throwaway certificate on a loopback address. |
|
nethttp
command
Command nethttp demonstrates embedding Sigil in an application-owned net/http server: validated configuration, the mounted authentication API, host routes protected by RequireSession, trusted host capabilities, abuse admission and graceful shutdown.
|
Command nethttp demonstrates embedding Sigil in an application-owned net/http server: validated configuration, the mounted authentication API, host routes protected by RequireSession, trusted host capabilities, abuse admission and graceful shutdown. |
|
oauth-smoke
command
Command oauth-smoke drives the link, sign-in and unlink journeys of the Google and GitHub adapters against the real providers from an operator's browser.
|
Command oauth-smoke drives the link, sign-in and unlink journeys of the Google and GitHub adapters against the real providers from an operator's browser. |
|
organization
command
Command organization runs a disposable, host-side organization journey.
|
Command organization runs a disposable, host-side organization journey. |
|
profile
command
Command profile runs a disposable custom-field journey against PostgreSQL: operator migrations, an owner update over HTTP, a back-office write of private and read-only fields, and the typed Go view.
|
Command profile runs a disposable custom-field journey against PostgreSQL: operator migrations, an owner update over HTTP, a back-office write of private and read-only fields, and the typed Go view. |
|
profile/fields
Package fields declares the example application's custom account fields.
|
Package fields declares the example application's custom account fields. |
|
profile/generate
command
Command generate rewrites the profile example's generated Go types and its OpenAPI export from fields.Schema.
|
Command generate rewrites the profile example's generated Go types and its OpenAPI export from fields.Schema. |
|
react
command
Command react is the Go-plus-React example: the shared HTTPS loopback host (core credentials, magic links, the OAuth plugin with a mock provider and a local mail preview) in front of a Node renderer that server-renders the React pages with @sigil-auth/react and forwards each request's session cookie to the API through a per-request server client.
|
Command react is the Go-plus-React example: the shared HTTPS loopback host (core credentials, magic links, the OAuth plugin with a mock provider and a local mail preview) in front of a Node renderer that server-renders the React pages with @sigil-auth/react and forwards each request's session cookie to the API through a per-request server client. |
|
internal
|
|
|
plugintest
Package plugintest supplies the same plugin fixtures with real engine stores.
|
Package plugintest supplies the same plugin fixtures with real engine stores. |
|
Package plugin defines explicitly registered, compiled extensions.
|
Package plugin defines explicitly registered, compiled extensions. |
|
apikey
Package apikey provides optional PostgreSQL/SQLite scoped API keys: an authentication mode distinct from browser sessions, for non-interactive callers of the host's own API.
|
Package apikey provides optional PostgreSQL/SQLite scoped API keys: an authentication mode distinct from browser sessions, for non-interactive callers of the host's own API. |
|
authserver
Package authserver lets a host operate an OAuth 2.0 authorization server and OpenID Connect provider for its own users, on PostgreSQL and SQLite.
|
Package authserver lets a host operate an OAuth 2.0 authorization server and OpenID Connect provider for its own users, on PostgreSQL and SQLite. |
|
internal/idtoken
Package idtoken holds the OpenID Connect ID-token claim contract shared by the provider sign-in plugins, so provider sign-in and organization SSO accept exactly the same tokens.
|
Package idtoken holds the OpenID Connect ID-token claim contract shared by the provider sign-in plugins, so provider sign-in and organization SSO accept exactly the same tokens. |
|
magiclink
Package magiclink provides optional, existing-account email sign-in using public plugin, storage, mail and session contracts.
|
Package magiclink provides optional, existing-account email sign-in using public plugin, storage, mail and session contracts. |
|
oauth
Package oauth implements optional authorization-code sign-in for already linked external identities.
|
Package oauth implements optional authorization-code sign-in for already linked external identities. |
|
oauth/github
Package github configures GitHub OAuth 2.0 sign-in for the oauth plugin.
|
Package github configures GitHub OAuth 2.0 sign-in for the oauth plugin. |
|
oauth/google
Package google configures Google OpenID Connect sign-in for the oauth plugin.
|
Package google configures Google OpenID Connect sign-in for the oauth plugin. |
|
oauth/internal/providertest
Package providertest is the PostgreSQL fixture shared by the provider adapter integration tests.
|
Package providertest is the PostgreSQL fixture shared by the provider adapter integration tests. |
|
organization
Package organization provides optional PostgreSQL/SQLite tenant membership and session context.
|
Package organization provides optional PostgreSQL/SQLite tenant membership and session context. |
|
passkey
Package passkey provides user-verified discoverable WebAuthn credentials.
|
Package passkey provides user-verified discoverable WebAuthn credentials. |
|
portability
Package portability holds the cross-engine plugin fixtures that keep the PostgreSQL and SQLite adapters honest about the same behavior: baseline migration, real factor/tenant/credential data preserved across disablement, and re-enablement after an upgrade.
|
Package portability holds the cross-engine plugin fixtures that keep the PostgreSQL and SQLite adapters honest about the same behavior: baseline migration, real factor/tenant/credential data preserved across disablement, and re-enablement after an upgrade. |
|
scim
Package scim provides optional organization-bound SCIM 2.0 provisioning and deprovisioning for PostgreSQL and SQLite (RFC 7643 and RFC 7644).
|
Package scim provides optional organization-bound SCIM 2.0 provisioning and deprovisioning for PostgreSQL and SQLite (RFC 7643 and RFC 7644). |
|
sso
Package sso provides optional organization-bound OpenID Connect and SAML 2.0 single sign-on for PostgreSQL and SQLite.
|
Package sso provides optional organization-bound OpenID Connect and SAML 2.0 single sign-on for PostgreSQL and SQLite. |
|
totp
Package totp implements optional password-plus-TOTP authentication on PostgreSQL.
|
Package totp implements optional password-plus-TOTP authentication on PostgreSQL. |
|
userfields
Package userfields adds explicit, typed custom fields to user accounts.
|
Package userfields adds explicit, typed custom fields to user accounts. |
|
Package storage defines identity records and transactional adapter guarantees.
|
Package storage defines identity records and transactional adapter guarantees. |
|
conformance
Package conformance is the reusable storage gate described in docs/storage-conformance.md.
|
Package conformance is the reusable storage gate described in docs/storage-conformance.md. |
|
postgres
Package postgres provides explicit versioned core PostgreSQL migrations and the transactional storage.Store adapter over them.
|
Package postgres provides explicit versioned core PostgreSQL migrations and the transactional storage.Store adapter over them. |
|
sqlite
Package sqlite implements Sigil storage on a local SQLite database.
|
Package sqlite implements Sigil storage on a local SQLite database. |