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

session

package
v0.5.3 Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2026 License: MIT Imports: 14 Imported by: 0

Documentation

Overview

Package session manages opaque, revocable credentials for typed model guards. Persistence adapters own atomic writes; application code supplies verified proofs and consumes models through the ordinary auth.Guard.

Index

Constants

View Source
const EncodedSecretBytes = credential.EncodedSecretBytes
View Source
const MaxImpersonation = 24 * time.Hour

MaxImpersonation bounds any impersonation session's absolute lifetime.

View Source
const MaxLifetime = 365 * 24 * time.Hour
View Source
const MaxPageSize = 1024
View Source
const MaxSessions = 1024
View Source
const SecretBytes = credential.SecretBytes

Variables

View Source
var ActorSessionEnded = safeerror.Sentinel(fault.Missing, "the impersonating actor's session has ended")

ActorSessionEnded is the cause Resume reports (as auth.Unauthenticated) when the impersonation ended but the original actor's session had been revoked or had expired meanwhile: the actor must log in again.

Functions

This section is empty.

Types

type Address

type Address struct {
	Namespace keyspace.Namespace
	Guard     auth.GuardName
	Provider  auth.ProviderName
	Model     string
}

Address binds persisted credentials to one application/environment, guard, provider and stored model namespace. It is the explicit adapter boundary.

func (Address) Key

func (a Address) Key() (string, error)

Key validates the address and returns its opaque persistence scope.

func (Address) SubjectKey

func (a Address) SubjectKey(identity model.Identity) (string, error)

SubjectKey returns the subject's opaque key within the validated address.

func (Address) Validate

func (a Address) Validate() error

Validate checks the namespace, guard, provider and model address components.

type Backend

type Backend interface {
	// Create atomically creates a session under the subject's capacity policy.
	Create(context.Context, Address, Creation) (Record, error)
	// Lookup resolves a live session by digest, optionally recording activity.
	Lookup(context.Context, Address, Digest, bool) (value.Optional[Record], error)
	// Rotate replaces a live session's secret hash and records activity without reviving
	// removed records.
	Rotate(context.Context, Address, Digest, Digest) (value.Optional[Record], error)
	// Revoke removes the session identified by its credential digest and reports whether
	// it existed.
	Revoke(context.Context, Address, Digest) (bool, error)
	// RevokeID removes the subject's identified session and reports whether it existed.
	RevokeID(context.Context, Address, model.Identity, model.ID[Record]) (bool, error)
	// RevokeAll removes all of the subject's sessions, serializing with creation.
	RevokeAll(context.Context, Address, model.Identity) (uint64, error)
	// List returns a bounded page of the subject's session records.
	List(context.Context, Address, model.Identity, int) ([]Record, error)
	// Prune removes a bounded batch of expired sessions.
	Prune(context.Context, Address, int) (uint64, error)
}

Backend owns one authoritative session store. Every mutation is atomic and executes without automatic retry. RevokeAll serializes with creation; sessions issued after that operation are new credentials. Lookup/rotation cannot revive a removed record. Clock sampling occurs after acquiring the relevant lock. Errors may mean an unknown write outcome; they are not missing credentials. Adapters return complete validated records and enforce bounded list/prune work.

type CheckedBackend

type CheckedBackend interface {
	// CreateChecked runs the proof check before credential locks and creates the session
	// in the same transaction.
	CreateChecked(context.Context, Address, Creation, func(context.Context, *database.Tx) error) (Record, error)
}

CheckedBackend verifies a proof's current model in the SAME transaction as creation, before acquiring credential subject locks. The check must lock the model and may run once only. A failed check creates nothing; never retry it.

type CompletionBackend

type CompletionBackend interface {
	DeadlineBackend
	// ConsumePendingIn locks, revalidates and provisionally deletes the exact pending-MFA
	// credential in the caller's transaction.
	ConsumePendingIn(context.Context, *database.Tx, Address, Record) error
}

CompletionBackend can replace a pending-MFA credential in checked creation. ConsumePendingIn joins the supplied transaction, locks and revalidates the exact pending record/hash/identity/expiry, and deletes it provisionally. It rejects full credentials. CreateBefore runs the check and creates through the ordinary creation path, then rechecks the pending deadline before commit. Both methods preserve rollback, never retry, and return no secret on failure.

type Config

type Config struct {
	Namespace            keyspace.Namespace
	Regular              Lifetime
	Remembered           Lifetime
	Pending              Lifetime
	MaxPerSubject        int
	MaxPendingPerSubject int
	Limit                auth.LimitPolicy
	MaxConcurrent        int
	Timeout              time.Duration
}

Config contains store-wide resource limits and explicit credential lifetimes. Changing policy affects new sessions; use revocation to invalidate old sessions. MaxPerSubject caps a subject's live full sessions per guard; Limit selects whether a new login evicts the oldest (default) or is rejected with auth.CredentialLimit. Pending-MFA and impersonation sessions never count toward it: each class has its own MaxPendingPerSubject cap and always replaces its oldest session, so MaxPerSubject + 2*MaxPendingPerSubject must not exceed MaxSessions. Expired sessions never count toward any cap.

func DefaultConfig

func DefaultConfig(namespace keyspace.Namespace) Config

DefaultConfig returns default regular, remembered and pending lifetimes, credential capacity and operation bounds.

func (Config) Validate

func (c Config) Validate() error

Validate checks namespace, lifetimes, capacity and timeouts; pending-MFA sessions cannot slide.

type ConfirmationBackend

type ConfirmationBackend interface {
	// Confirm stamps confirmation on a live, fully authenticated session, omitting the
	// result when it is gone.
	Confirm(context.Context, Address, model.Identity, model.ID[Record]) (value.Optional[Record], error)
	// ConfirmedWithin checks whether the live session confirmed within the duration of the
	// authority's current time.
	ConfirmedWithin(context.Context, Address, model.Identity, model.ID[Record], time.Duration) (bool, error)
}

ConfirmationBackend stamps ConfirmedAt on one live, fully authenticated session of the subject and returns the updated record, or omits it when the session is gone. ConfirmedWithin reports whether that live session confirmed within the duration of the backend's current time. Both sample its clock.

type Creation

type Creation struct {
	ID             model.ID[Record]
	Subject        model.Identity
	Hash           Digest
	Assurance      auth.Assurance
	Remember       bool
	Lifetime       Lifetime
	Maximum        int
	PendingMaximum int
	Limit          auth.LimitPolicy
	Device         auth.Device
	// Impersonator marks an impersonation session. Impersonation sessions count
	// only against PendingMaximum, like pending MFA, so they never evict or are
	// rejected by the subject's own sessions.
	Impersonator value.Optional[Impersonator]
}

Creation contains verified identity metadata and a newly generated hash. Maximum is the live full-session bound and PendingMaximum the live pending-MFA bound, both enforced under the subject's write lock for the credential's own kind. Limit selects eviction or rejection for full sessions; pending sessions always evict their oldest. Expired rows never count.

func (Creation) At

func (c Creation) At(address Address, now time.Time) (Record, error)

At validates creation and constructs a record using now truncated to UTC microseconds.

func (Creation) Validate

func (c Creation) Validate(address Address) error

Validate checks subject ownership, credential capacity, device, assurance and lifetime, including pending and impersonation restrictions.

type DeadlineBackend

type DeadlineBackend interface {
	CheckedBackend
	// CreateBefore performs checked creation and rechecks the supplied deadline before
	// commit, rolling back joined writes on expiry.
	CreateBefore(context.Context, Address, Creation, temporal.DateTime, func(context.Context, *database.Tx) error) (Record, error)
}

DeadlineBackend performs checked creation and rechecks an existing credential's deadline before commit. Expiry rolls back all joined writes.

type Digest

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

Digest is a SHA-256 credential hash at the explicit adapter boundary. It cannot be submitted in place of the raw session secret.

func HashSecret

func HashSecret(value secret.String) (Digest, error)

HashSecret accepts only a canonical 256-bit random session-secret encoding. Malformed inputs fail before any persistence operation.

func ParseDigest

func ParseDigest(text string) (Digest, error)

ParseDigest restores a session digest from its hexadecimal representation.

func (Digest) Equal

func (d Digest) Equal(other Digest) bool

Equal compares session digests.

func (Digest) Format

func (Digest) Format(s fmt.State, _ rune)

Format writes the label "session digest" without exposing the value.

func (Digest) Hex

func (d Digest) Hex() string

Hex returns the digest's hexadecimal persistence representation.

func (Digest) IsZero

func (d Digest) IsZero() bool

IsZero reports whether the digest is uninitialized.

type ID

type ID[M any] struct {
	// contains filtered or unexported fields
}

ID is a public session identifier owned by model M. It is not an authentication secret or a model primary key, and remains stable across session rotation.

func ParseID

func ParseID[M any](text string) (ID[M], error)

ParseID parses a session identifier while retaining model ownership.

func (ID[M]) IsZero

func (id ID[M]) IsZero() bool

IsZero reports whether the identifier is uninitialized.

func (ID[M]) MarshalText

func (id ID[M]) MarshalText() ([]byte, error)

MarshalText encodes the session identifier in text form.

func (ID[M]) String

func (id ID[M]) String() string

String returns the session identifier's text representation.

type Impersonation

type Impersonation[A model.Identifiable, AK any, M model.Identifiable, K any] struct {
	// contains filtered or unexported fields
}

Impersonation lets an authenticated actor of one session binding act as a model of another (or the same) binding, for support and administration. The impersonation session records the actor, its guard and its own session, so the original actor stays accessible and the session is visibly marked: Info.Impersonated, Sessions.RequireNotImpersonating and ConfirmCurrent refuse sensitive operations and mint no other credential (CurrentProof, RevokeOthers). Sessions are bounded by a maximum duration, never remembered, counted apart from the subject's own sessions, and end when the actor's own session is revoked or expires, so both bindings must share one store.

Authorize the actor (for example with a policy on the target model) before Start: the binding does not decide who may impersonate whom. Observers receive EventImpersonationStarted and EventImpersonationStopped, which an audit or outbox observer can persist.

func NewImpersonation

func NewImpersonation[A model.Identifiable, AK any, M model.Identifiable, K any](actors *Sessions[A, AK], targets *Sessions[M, K], maximum time.Duration) (*Impersonation[A, AK, M, K], error)

NewImpersonation validates the duration bound and requires actor and target sessions to share the same store.

func (*Impersonation[A, AK, M, K]) Actor

func (i *Impersonation[A, AK, M, K]) Actor(ctx context.Context) (value.Optional[A], error)

Actor returns the original actor behind the current impersonation session of the targets guard, loaded through the actors provider, or an omitted value when the current session is not impersonated.

func (*Impersonation[A, AK, M, K]) Actors

func (i *Impersonation[A, AK, M, K]) Actors() *Sessions[A, AK]

Actors and Targets return the bound session bindings.

func (*Impersonation[A, AK, M, K]) Resume

func (i *Impersonation[A, AK, M, K]) Resume(ctx context.Context) (Issued[A, AK], error)

Resume ends the current impersonation session and returns the original actor's session with a fresh secret, for flows where actor and target share one cookie. The actor session recorded at Start is rotated in place: it keeps its ID, creation time, absolute expiry and remember policy, so impersonation can never extend an actor's session. When the actor's session was revoked, rotated or expired meanwhile, or the actor is no longer eligible, the impersonation still ends and Resume fails with auth.Unauthenticated caused by ActorSessionEnded: the actor must log in again.

func (*Impersonation[A, AK, M, K]) Start

func (i *Impersonation[A, AK, M, K]) Start(ctx context.Context, target model.Reference[M, K], duration time.Duration) (Issued[M, K], error)

Start issues an impersonation session for target, marked with the current actor session of the actors guard, lasting at most duration (and the configured maximum). The actor's own session is not revoked; Resume or Stop returns to it. Nested impersonation and self-impersonation are refused; the target must exist and be eligible through its provider.

func (*Impersonation[A, AK, M, K]) Stop

func (i *Impersonation[A, AK, M, K]) Stop(ctx context.Context) error

Stop ends the current impersonation session. Use it when the actor keeps its own credential (another cookie or token); its session is untouched.

func (*Impersonation[A, AK, M, K]) Targets

func (i *Impersonation[A, AK, M, K]) Targets() *Sessions[M, K]

Targets returns the target session binding.

func (*Impersonation[A, AK, M, K]) Validate

func (i *Impersonation[A, AK, M, K]) Validate() error

Validate checks that actor and target session bindings are configured.

func (*Impersonation[A, AK, M, K]) WithObserver

func (i *Impersonation[A, AK, M, K]) WithObserver(observer auth.Observer) (*Impersonation[A, AK, M, K], error)

WithObserver returns a copy reporting impersonation start and stop.

type Impersonator

type Impersonator struct {
	Subject model.Identity
	Guard   auth.GuardName
	Session model.ID[Record]
}

Impersonator is the original actor of an impersonation session: its stored identity, the guard that authenticated it and that actor's own session, which Impersonation.Resume and Stop use to return. It is metadata, never authority.

func (Impersonator) Validate

func (i Impersonator) Validate() error

Validate checks the actor identity, guard and nonzero actor session identifier.

type Info

type Info[M, K any] struct {
	// contains filtered or unexported fields
}

Info exposes session metadata with a concrete stored subject reference. It carries no secret/hash and does not authorize the caller to act as that subject.

func (Info[M, K]) Assurance

func (i Info[M, K]) Assurance() auth.Assurance

Assurance returns the session's authentication assurance.

func (Info[M, K]) ConfirmedAt

func (i Info[M, K]) ConfirmedAt() value.Optional[temporal.DateTime]

ConfirmedAt is when the holder last re-entered its password in this session.

func (Info[M, K]) CreatedAt

func (i Info[M, K]) CreatedAt() temporal.DateTime

CreatedAt returns the session's creation time.

func (Info[M, K]) Device

func (i Info[M, K]) Device() auth.Device

Device is the client metadata captured when the session was issued.

func (Info[M, K]) ExpiresAt

func (i Info[M, K]) ExpiresAt() temporal.DateTime

ExpiresAt returns the session's absolute expiry.

func (Info[M, K]) Format

func (Info[M, K]) Format(s fmt.State, _ rune)

Format writes the label "session metadata" without exposing the value.

func (Info[M, K]) ID

func (i Info[M, K]) ID() ID[M]

ID returns the model-owned session identifier.

func (Info[M, K]) IdleExpiresAt

func (i Info[M, K]) IdleExpiresAt() temporal.DateTime

IdleExpiresAt returns the session's current inactivity deadline.

func (Info[M, K]) Impersonated

func (i Info[M, K]) Impersonated() bool

Impersonated reports whether this session was started by impersonation.

func (Info[M, K]) Impersonator

func (i Info[M, K]) Impersonator() value.Optional[Impersonator]

Impersonator is the original actor when this is an impersonation session.

func (Info[M, K]) LastSeenAt

func (i Info[M, K]) LastSeenAt() temporal.DateTime

LastSeenAt returns the session's recorded activity time.

func (Info[M, K]) Remembered

func (i Info[M, K]) Remembered() bool

Remembered reports whether the session uses the remembered lifetime policy.

func (Info[M, K]) Subject

func (i Info[M, K]) Subject() model.Reference[M, K]

Subject returns the session's typed model reference.

type IssueOptions

type IssueOptions struct{ Remember bool }

IssueOptions selects persistence policy after credential verification. Pending MFA credentials cannot request remember-me persistence.

type Issued

type Issued[M, K any] struct {
	// contains filtered or unexported fields
}

Issued owns the newly generated secret. Only Secret exposes it for the explicit transport boundary; routine formatting and JSON never serialize credentials. Losing the response may leave an orphan session until expiry or revocation.

func (Issued[M, K]) Format

func (Issued[M, K]) Format(s fmt.State, _ rune)

Format writes the label "issued session" without exposing the value.

func (Issued[M, K]) Info

func (i Issued[M, K]) Info() Info[M, K]

Info returns the issued session's safe metadata.

func (Issued[M, K]) Secret

func (i Issued[M, K]) Secret() secret.String

Secret explicitly exposes the issued session secret wrapper for delivery.

type Lifetime

type Lifetime struct {
	Idle     time.Duration
	Absolute time.Duration
	Sliding  bool
}

Lifetime fixes server-side expiry at creation. Sliding can extend idle expiry but never the absolute deadline. Rotation never restarts the absolute lifetime.

func (Lifetime) TouchInterval

func (l Lifetime) TouchInterval() time.Duration

TouchInterval is the minimum age of LastSeenAt before a sliding session's activity is written again: max(1 minute, Idle/20), but never more than half the idle lifetime, so a short idle window still slides for an active user. Skipping more frequent writes avoids a row update per request; idle expiry may therefore arrive up to this interval earlier than Idle after the last request.

func (Lifetime) Validate

func (l Lifetime) Validate() error

Validate requires whole-microsecond durations with positive idle expiry and an absolute expiry between idle and MaxLifetime.

type Record

type Record struct {
	ID            model.ID[Record]
	Address       Address
	Subject       model.Identity
	Hash          Digest
	Assurance     auth.Assurance
	Remember      bool
	Lifetime      Lifetime
	CreatedAt     temporal.DateTime
	LastSeenAt    temporal.DateTime
	IdleExpiresAt temporal.DateTime
	ExpiresAt     temporal.DateTime
	Device        auth.Device
	// ConfirmedAt is when the holder last re-entered its password (see
	// Sessions.ConfirmCurrent). It never outlives the session.
	ConfirmedAt value.Optional[temporal.DateTime] `json:",omitzero"`
	// Impersonator marks an impersonation session with its original actor.
	Impersonator value.Optional[Impersonator] `json:",omitzero"`
}

Record is a bounded, immutable-value adapter result. Adapters never return a raw secret. Public typed consumers receive Info or Issued, not these records.

func (Record) Format

func (Record) Format(s fmt.State, _ rune)

Format writes the label "session record" without exposing the value.

func (Record) Live

func (r Record) Live(now time.Time) bool

Live reports whether now is strictly before both idle and absolute expiry.

func (Record) NeedsTouch

func (r Record) NeedsTouch(now time.Time) bool

NeedsTouch reports whether a live sliding session should record activity now.

func (Record) Touch

func (r Record) Touch(now time.Time) (Record, bool, error)

Touch keeps monotonic activity across small server clock regressions. It never revives an expired record and never extends beyond its original absolute limit.

func (Record) Validate

func (r Record) Validate(address Address) error

Validate checks address ownership, identity, assurance, lifetime consistency, confirmation, impersonation and device metadata.

type ResumptionBackend

type ResumptionBackend interface {
	// ResumeActor runs check and rotates the exact live original actor session in one
	// transaction, omitting revoked, rotated, expired or impersonated records.
	ResumeActor(context.Context, Address, Record, Digest, func(context.Context, *database.Tx) error) (value.Optional[Record], error)
}

ResumptionBackend returns to the original actor's session after impersonation. ResumeActor runs check first, then, in the same transaction and under the subject lock, locks the exact live, fully authenticated, unimpersonated record (same hash, ID, subject, creation time and absolute expiry) and replaces its secret hash with next, recording activity. The ID, creation time, absolute expiry and remember policy never change. A revoked, rotated, expired or impersonated record returns an omitted value and changes nothing. It never retries.

type SelectiveBackend

type SelectiveBackend interface {
	// RevokeOthers removes every session of the subject except keep, returning the count.
	RevokeOthers(context.Context, Address, model.Identity, model.ID[Record]) (uint64, error)
}

SelectiveBackend revokes every session of a subject in this address except keep, under the same subject lock as creation. It returns the removed count.

type Sessions

type Sessions[M model.Identifiable, K any] struct {
	// contains filtered or unexported fields
}

Sessions binds one stored model/provider/guard/source to a shared store. Its Guard is constructed once; persisted credentials cannot be rebound to a different guard name by extracting an unscoped strategy. Construction performs no I/O.

func New

func New[M model.Identifiable, K any](store *Store, name auth.GuardName, provider auth.Provider[M, K], source auth.CredentialName) (*Sessions[M, K], error)

New validates and binds a session store, provider, guard name and credential source.

func (*Sessions[M, K]) CompleteMFA

func (s *Sessions[M, K]) CompleteMFA(ctx context.Context, raw secret.String, factor auth.SecondFactor[M, K], options IssueOptions) (Issued[M, K], error)

CompleteMFA replaces a live pending credential from THIS guard with one fresh authenticated credential. The lookup is only a locator; checked creation revalidates and consumes it with the current model and factor in one transaction. Full, expired, revoked, wrong-guard or already-consumed credentials are rejected. No reusable authenticated proof escapes, and failures return no new secrets. Options belong to the server's login policy, not unvalidated client claims.

func (*Sessions[M, K]) ConfirmCurrent

func (s *Sessions[M, K]) ConfirmCurrent(ctx context.Context) (Info[M, K], error)

ConfirmCurrent records that the holder of the current session re-entered its password now. Call it only after verifying the password (for example with auth.PasswordLogin.Confirm); RequireConfirmed then admits sensitive actions.

func (*Sessions[M, K]) Current

func (s *Sessions[M, K]) Current(ctx context.Context) (Info[M, K], error)

Current returns the metadata of the session that authenticated this guard in the current auth scope (for example to mark "this device" in List results by comparing IDs). It reuses the scope's verification; no second lookup runs.

func (*Sessions[M, K]) CurrentProof

func (s *Sessions[M, K]) CurrentProof(ctx context.Context) (auth.Proof[M, K], error)

CurrentProof returns a proof for the current request's model, for issuing a related credential (for example an API token) without constructing an unrestricted proof from a submitted identity. Sessions carry no scope grants. An impersonation session is refused with auth.ImpersonationForbidden: the impersonator must not mint an unmarked token or session for the subject.

func (*Sessions[M, K]) Guard

func (s *Sessions[M, K]) Guard() auth.Guard[M]

Guard returns the session authentication guard, or an undefined guard for a nil binding.

func (*Sessions[M, K]) Issue

func (s *Sessions[M, K]) Issue(ctx context.Context, proof auth.Proof[M, K], options IssueOptions) (Issued[M, K], error)

Issue persists a verified proof. This is a trusted login boundary, not password verification. A proof must come from a trusted authentication flow; a parsed client identity or request DTO must never be promoted to a proof here.

func (*Sessions[M, K]) List

func (s *Sessions[M, K]) List(ctx context.Context, reference model.Reference[M, K]) ([]Info[M, K], error)

List returns at most MaxSessions live sessions for this model identity. It exposes typed metadata, never stored hashes or raw secrets. It does not itself authorize the calling user to inspect another user; use an ordinary policy.

func (*Sessions[M, K]) Logout

func (s *Sessions[M, K]) Logout(ctx context.Context, credential secret.String) (bool, error)

Logout revokes a presented session secret and reports EventLogout when it removed a session. Browser adapters use it for the cookie's own logout.

func (*Sessions[M, K]) Prune

func (s *Sessions[M, K]) Prune(ctx context.Context, limit int) (uint64, error)

Prune removes up to limit expired sessions within this binding's address.

func (*Sessions[M, K]) PruneExpired

func (s *Sessions[M, K]) PruneExpired(ctx context.Context, batch, maxBatches int) (uint64, error)

PruneExpired prunes expired sessions of this guard in batches of batch rows, stopping after a short batch or maxBatches, and reports the rows removed. Schedule it from the application calendar or the configured housekeeping schedule; the auth package does not depend on the scheduler.

func (*Sessions[M, K]) RequireConfirmed

func (s *Sessions[M, K]) RequireConfirmed(ctx context.Context, within time.Duration) error

RequireConfirmed returns auth.ConfirmationRequired unless the current session confirmed its password within the given duration, checked against the backend's current time rather than the scope's cached metadata.

func (*Sessions[M, K]) RequireNotImpersonating

func (s *Sessions[M, K]) RequireNotImpersonating(ctx context.Context) error

RequireNotImpersonating returns auth.ImpersonationForbidden when the current session is an impersonation session. Call it before sensitive operations such as changing the password, email or MFA factors, or deleting the account.

func (*Sessions[M, K]) Revocation

func (s *Sessions[M, K]) Revocation() (auth.Revocation[M, K], error)

Revocation contributes this bound guard to auth.NewRevocations. Construct the group once and pass its Invalidate method to password-reset/domain callbacks.

func (*Sessions[M, K]) Revoke

func (s *Sessions[M, K]) Revoke(ctx context.Context, credential secret.String) (bool, error)

Revoke hashes the credential and removes its session, reporting whether it existed.

func (*Sessions[M, K]) RevokeAll

func (s *Sessions[M, K]) RevokeAll(ctx context.Context, reference model.Reference[M, K]) (uint64, error)

RevokeAll removes the reference's sessions after checking provider ownership.

func (*Sessions[M, K]) RevokeAllIn

func (s *Sessions[M, K]) RevokeAllIn(ctx context.Context, tx *database.Tx, reference model.Reference[M, K]) (uint64, error)

RevokeAllIn joins a caller's transaction. Its count is provisional and the caller must propagate errors. It never acquires a model lock; credential-change orchestration must lock that model first. Unsupported adapters fail closed.

func (*Sessions[M, K]) RevokeCurrent

func (s *Sessions[M, K]) RevokeCurrent(ctx context.Context) (bool, error)

RevokeCurrent revokes the session that authenticated this request, for API logout on an authenticated route. It reports EventLogout when it removed it.

func (*Sessions[M, K]) RevokeID

func (s *Sessions[M, K]) RevokeID(ctx context.Context, reference model.Reference[M, K], id ID[M]) (bool, error)

RevokeID removes a listed session belonging to this exact subject and guard. The identifier is not authority; authorize the caller before choosing a subject.

func (*Sessions[M, K]) RevokeOthers

func (s *Sessions[M, K]) RevokeOthers(ctx context.Context) (uint64, error)

RevokeOthers revokes every other session of the current subject in this guard while keeping the current one ("log out other devices"). It runs under the subject lock shared with issuance and reports EventOtherDevicesLoggedOut. Combine with the model's other credential stores for a full sign-out.

func (*Sessions[M, K]) Rotate

func (s *Sessions[M, K]) Rotate(ctx context.Context, credential secret.String) (Issued[M, K], error)

Rotate atomically changes a live session's secret. The previous secret becomes invalid, while session ID, assurance, creation time and absolute expiry persist. Parallel rotations have at most one winner. Failed/uncertain writes are not retried.

func (*Sessions[M, K]) Validate

func (s *Sessions[M, K]) Validate() error

Validate checks the session store and guard binding.

func (*Sessions[M, K]) WithObserver

func (s *Sessions[M, K]) WithObserver(observer auth.Observer) (*Sessions[M, K], error)

WithObserver returns a binding sharing this guard that reports EventLogin for full issuance (including MFA completion), EventLogout for Logout and RevokeCurrent, and EventOtherDevicesLoggedOut for RevokeOthers.

type Store

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

Store borrows a backend and owns limits shared by its typed session bindings. The caller owns the backend's database/connection lifecycle.

func NewStore

func NewStore(backend Backend, config Config) (*Store, error)

NewStore validates and borrows backend and creates bounded session-operation admission.

type TransactionalBackend

type TransactionalBackend interface {
	// RevokeAllIn removes the subject's sessions within the caller-owned transaction,
	// without committing or retrying.
	RevokeAllIn(context.Context, *database.Tx, Address, model.Identity) (uint64, error)
}

TransactionalBackend joins a caller-owned transaction. It must verify pool ownership, restore schema state, preserve rollback, and never commit or retry.

Directories

Path Synopsis
Package postgres persists session credentials through Foundry-owned PostgreSQL models and explicit migrations.
Package postgres persists session credentials through Foundry-owned PostgreSQL models and explicit migrations.

Jump to

Keyboard shortcuts

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