Documentation
¶
Overview ¶
Package token manages model-owned personal and renewable access credentials. Persistence adapters own atomic refresh/reuse behavior. Guards resolve current models and use auth.AccessScopes as a credential ceiling, never as permissions.
Index ¶
- Constants
- type Address
- type Backend
- type CheckedBackend
- type CompletionBackend
- type Config
- type Creation
- type Digest
- type GraceBackend
- type ID
- type Info
- func (i Info[M, K]) AccessExpiresAt() temporal.DateTime
- func (i Info[M, K]) Assurance() auth.Assurance
- func (i Info[M, K]) CreatedAt() temporal.DateTime
- func (i Info[M, K]) Device() auth.Device
- func (i Info[M, K]) ExpiresAt() temporal.DateTime
- func (Info[M, K]) Format(s fmt.State, _ rune)
- func (i Info[M, K]) Generation() uint32
- func (i Info[M, K]) ID() ID[M]
- func (i Info[M, K]) IssuedAt() temporal.DateTime
- func (i Info[M, K]) LastSeenAt() temporal.DateTime
- func (i Info[M, K]) Mode() Mode
- func (i Info[M, K]) Name() string
- func (i Info[M, K]) RefreshExpiresAt() value.Optional[temporal.DateTime]
- func (i Info[M, K]) Scopes() auth.AccessScopes[M]
- func (i Info[M, K]) Subject() model.Reference[M, K]
- type IssueOptions
- type Issued
- type Lifetime
- type Lifetimes
- type Mode
- type Option
- type Record
- func (Record) Format(s fmt.State, _ rune)
- func (r Record) Live(now time.Time) bool
- func (r Record) LiveAccess(now time.Time) bool
- func (r Record) LiveAccessWithin(now time.Time, grace time.Duration) bool
- func (r Record) LiveRefresh(now time.Time) bool
- func (r Record) Refreshed(now time.Time, access, refresh Digest) (Record, bool, error)
- func (r Record) Validate(address Address) error
- type RefreshRevocationBackend
- type SelectiveBackend
- type Store
- type Ticket
- type TicketBackend
- type TicketRecord
- type Tokens
- func (t *Tokens[M, K]) CompleteMFA(ctx context.Context, raw secret.String, factor auth.SecondFactor[M, K], ...) (Issued[M, K], error)
- func (t *Tokens[M, K]) Current(ctx context.Context) (Info[M, K], error)
- func (t *Tokens[M, K]) CurrentProof(ctx context.Context) (auth.Proof[M, K], error)
- func (t *Tokens[M, K]) Guard() auth.Guard[M]
- func (t *Tokens[M, K]) Issue(ctx context.Context, proof auth.Proof[M, K], options IssueOptions[M]) (Issued[M, K], error)
- func (t *Tokens[M, K]) IssueTicket(ctx context.Context) (Ticket[M, K], error)
- func (t *Tokens[M, K]) List(ctx context.Context, reference model.Reference[M, K]) ([]Info[M, K], error)
- func (t *Tokens[M, K]) Logout(ctx context.Context, access secret.String) (bool, error)
- func (t *Tokens[M, K]) LogoutRefresh(ctx context.Context, refresh secret.String) (bool, error)
- func (t *Tokens[M, K]) Prune(ctx context.Context, limit int) (uint64, error)
- func (t *Tokens[M, K]) PruneExpired(ctx context.Context, batch, maxBatches int) (uint64, error)
- func (t *Tokens[M, K]) RedeemTicket(ctx context.Context, raw secret.String) (value.Optional[auth.BoundCredential], error)
- func (t *Tokens[M, K]) Refresh(ctx context.Context, raw secret.String) (Issued[M, K], error)
- func (t *Tokens[M, K]) Revocation() (auth.Revocation[M, K], error)
- func (t *Tokens[M, K]) Revoke(ctx context.Context, access secret.String) (bool, error)
- func (t *Tokens[M, K]) RevokeAll(ctx context.Context, reference model.Reference[M, K]) (uint64, error)
- func (t *Tokens[M, K]) RevokeAllIn(ctx context.Context, tx *database.Tx, reference model.Reference[M, K]) (uint64, error)
- func (t *Tokens[M, K]) RevokeCurrent(ctx context.Context) (bool, error)
- func (t *Tokens[M, K]) RevokeID(ctx context.Context, reference model.Reference[M, K], id ID[M]) (bool, error)
- func (t *Tokens[M, K]) RevokeOthers(ctx context.Context) (uint64, error)
- func (t *Tokens[M, K]) TicketSource() auth.CredentialName
- func (t *Tokens[M, K]) Touch(ctx context.Context, access secret.String) (bool, error)
- func (t *Tokens[M, K]) Validate() error
- func (t *Tokens[M, K]) ValidateTickets() error
- func (t *Tokens[M, K]) WithObserver(observer auth.Observer) (*Tokens[M, K], error)
- type TransactionalBackend
Constants ¶
const MaxFamilyTickets = 64
const MaxLifetime = 365 * 24 * time.Hour
const MaxPrefixBytes = 16
MaxPrefixBytes bounds Config.Prefix.
const MaxPruneFamilies = 1024
const MaxRotations = 4096
const MaxTicketLifetime = 5 * time.Minute
MaxTicketLifetime and MaxFamilyTickets bound single-use handshake tickets.
const MaxTokens = 1024
Variables ¶
This section is empty.
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 tokens to an application, environment, model/provider and guard. It is an infrastructure boundary, not an application identity API.
func (Address) SubjectKey ¶
SubjectKey returns the subject's opaque key within the validated address.
type Backend ¶
type Backend interface {
// Create atomically creates a token under the subject's capacity policy.
Create(context.Context, Address, Creation) (Record, error)
// Lookup resolves a live token by digest, optionally recording activity.
Lookup(context.Context, Address, Digest, bool) (value.Optional[Record], error)
// Refresh atomically consumes a refresh generation and creates its successor; reuse
// revokes the family and returns omission.
Refresh(context.Context, Address, Digest, Digest, Digest) (value.Optional[Record], error)
// Revoke removes the token family identified by its credential digest and reports
// whether it existed.
Revoke(context.Context, Address, Digest) (bool, error)
// RevokeID removes the subject's identified token family and reports whether it
// existed.
RevokeID(context.Context, Address, model.Identity, model.ID[Record]) (bool, error)
// RevokeAll removes all of the subject's token families, serializing with creation.
RevokeAll(context.Context, Address, model.Identity) (uint64, error)
// List returns a bounded page of the subject's token records.
List(context.Context, Address, model.Identity, int) ([]Record, error)
// Prune removes a bounded batch of expired token families.
Prune(context.Context, Address, int) (uint64, error)
}
Backend is an authoritative hash-only store. Every mutation owns one transaction and runs without automatic retries. Stable subject locks serialize creation, revocation and refresh. Sample server time after the relevant lock is acquired. Lookup only accepts the family's current access generation. Refresh atomically consumes the current generation and creates its successor, preserving the family lifetime and grant. A consumed refresh hash revokes the entire family, committing that revocation before returning an omitted result. Never roll it back merely because the public refresh operation is rejected. At the rotation limit, revoke rather than accumulate unbounded history. Retain consumed generations until the family expires or is revoked. Concurrent use may yield one success followed by family revocation; no replay grace period is implied. An unknown commit outcome returns an error, never a partial record or new secret.
type CheckedBackend ¶
type CheckedBackend interface {
// CreateChecked runs the proof check before credential locks and creates the token 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 {
CheckedBackend
// ConsumePendingIn locks, revalidates and provisionally deletes the exact pending-MFA
// credential in the caller's transaction.
ConsumePendingIn(context.Context, *database.Tx, Address, Record) error
// CreateBefore performs checked creation and rechecks the pending deadline before
// commit, rolling back joined writes on expiry.
CreateBefore(context.Context, Address, Creation, temporal.DateTime, func(context.Context, *database.Tx) error) (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
Personal Lifetime
Renewable Lifetime
Challenge Lifetime
MaxPerSubject int
MaxPendingPerSubject int
Limit auth.LimitPolicy
MaxRotations int
AccessGrace time.Duration
Prefix string
MaxConcurrent int
Timeout time.Duration
TicketLifetime time.Duration
MaxTicketsPerFamily int
}
Config bounds the store and fixes new tokens' lifetimes. MaxPerSubject caps a subject's live personal/renewable families per guard; Limit selects rejection with auth.CredentialLimit (default) or evicting the oldest. Pending-MFA challenge tokens only count toward MaxPendingPerSubject and always replace the oldest pending one. Expired families never count. AccessGrace keeps a refreshed family's previous access token valid for this long after the refresh (never beyond its own expiry), so requests already in flight with it do not fail; zero disables it. Prefix is prepended to newly issued access/refresh secrets for secret scanning (for example "myapp_"); secrets with or without a prefix are accepted, since only the random part is hashed. TicketLifetime bounds a single-use handshake ticket from IssueTicket (between one second and MaxTicketLifetime; zero disables tickets), and MaxTicketsPerFamily caps one family's unexpired tickets, dropping the oldest.
func DefaultConfig ¶
DefaultConfig returns default token lifetimes, capacity, rotation, access-grace, ticket and operation bounds.
type Creation ¶
type Creation struct {
ID model.ID[Record]
Subject model.Identity
Name string
Scopes []auth.AccessScopeName
Mode Mode
Assurance auth.Assurance
AccessHash Digest
RefreshHash value.Optional[Digest]
Lifetime Lifetime
RotationLimit uint32
Maximum int
PendingMaximum int
Limit auth.LimitPolicy
Device auth.Device
}
Creation is a trusted, bounded issuance request. Backend.Create enforces Maximum live personal/renewable families and PendingMaximum live challenge families, each counting only its own kind, while holding the stable subject lock. Limit selects rejection or eviction for full families; challenges always evict their oldest. Expired families never count.
type Digest ¶
type Digest struct {
// contains filtered or unexported fields
}
Digest is a token-store hash. It is distinct from a session digest and cannot substitute for an opaque credential supplied at a transport boundary.
func HashSecret ¶
HashSecret accepts the canonical 256-bit random encoding, optionally preceded by a Config.Prefix-style prefix. Only the random part is hashed, so changing the configured prefix never invalidates existing tokens.
func ParseDigest ¶
ParseDigest restores a token digest from its hexadecimal representation.
type GraceBackend ¶
type GraceBackend interface {
// LookupWithin accepts the current access generation or its immediate predecessor
// within grace and its own access expiry.
LookupWithin(context.Context, Address, Digest, time.Duration) (value.Optional[Record], error)
}
GraceBackend additionally accepts the generation immediately before the family's current one, with Record.SupersededAt set, while the backend's clock is within grace of the successor's issue time and before its own access expiry. It never accepts older generations, and refresh-token reuse still revokes the family.
type ID ¶
type ID[M any] struct { // contains filtered or unexported fields }
ID is a model-owned token family identifier, never an authentication secret. It remains stable across refresh. Explicit subject authorization is still needed.
func (ID[M]) MarshalText ¶
MarshalText encodes the token identifier in text form.
type Info ¶
type Info[M, K any] struct { // contains filtered or unexported fields }
Info exposes immutable metadata and a concrete stored model reference. It contains neither raw credentials nor hashes and does not authorize its caller.
func (Info[M, K]) AccessExpiresAt ¶
AccessExpiresAt returns the access credential's expiry.
func (Info[M, K]) Generation ¶
Generation returns the token family's rotation generation.
func (Info[M, K]) LastSeenAt ¶
LastSeenAt returns the token's recorded activity time.
func (Info[M, K]) RefreshExpiresAt ¶
RefreshExpiresAt returns the optional refresh credential deadline.
func (Info[M, K]) Scopes ¶
func (i Info[M, K]) Scopes() auth.AccessScopes[M]
Scopes returns the token's immutable model-owned capability grants.
type IssueOptions ¶
type IssueOptions[M any] struct { Name string Scopes auth.AccessScopes[M] Refresh bool }
IssueOptions is chosen by trusted credential verification, not mass-assigned from a login DTO. Requested scopes must fit this binding's declared ceiling. A scoped proof can only issue a subset of its own grants.
type Issued ¶
type Issued[M, K any] struct { // contains filtered or unexported fields }
Issued retains raw credentials for explicit transport delivery only. Routine formatting and JSON do not disclose them. Nonrenewable tokens omit refresh.
func (Issued[M, K]) AccessSecret ¶
AccessSecret explicitly exposes the issued access secret wrapper for delivery.
type Lifetime ¶
Lifetime preserves a family's absolute expiry across every refresh. Access activity never extends refresh idle expiry. Only successful refresh does so.
type Lifetimes ¶
type Lifetimes struct{ Personal, Renewable, Challenge Lifetime }
Lifetimes are one guard's issuance lifetimes by mode.
type Mode ¶
type Mode uint8
Mode distinguishes nonrenewable personal credentials, renewable pairs and short-lived MFA challenges. A challenge never carries ordinary access scopes.
type Option ¶
type Option func(*options) error
Option configures one token binding at construction.
func WithLifetimes ¶
WithLifetimes shortens this guard's issuance lifetimes, for example admin tokens that expire sooner than user tokens issued from the same store. A zero Lifetime keeps the store's for that mode. The store's lifetimes are the ceiling: no duration may exceed the store's for its mode, so the configured store bounds every guard. Each lifetime must be valid for its mode, and the renewable access lifetime must still cover Config.AccessGrace. A family keeps the lifetime it was issued with across refreshes.
type Record ¶
type Record struct {
ID model.ID[Record]
Address Address
Subject model.Identity
Name string
Scopes []auth.AccessScopeName
Mode Mode
Assurance auth.Assurance
AccessHash Digest
RefreshHash value.Optional[Digest]
Lifetime Lifetime
RotationLimit uint32
Generation uint32
CreatedAt temporal.DateTime
IssuedAt temporal.DateTime
LastSeenAt temporal.DateTime
AccessExpiresAt temporal.DateTime
RefreshExpiresAt value.Optional[temporal.DateTime]
ExpiresAt temporal.DateTime
Device auth.Device
// SupersededAt is set only when Lookup returns the generation immediately
// before the family's current one: the successor's issue time. Its access
// secret authenticates only within Config.AccessGrace of that time.
SupersededAt value.Optional[temporal.DateTime] `json:",omitzero"`
}
Record is the explicit adapter boundary for the current token generation. It contains no raw secret. Adapters transfer ownership of the bounded scope slice; typed application code receives immutable Info instead of this record.
func (Record) LiveAccess ¶
LiveAccess reports whether now is strictly before access and absolute expiry.
func (Record) LiveAccessWithin ¶
LiveAccessWithin reports access validity, allowing a superseded generation only until grace after its successor was issued (never past its own expiry).
func (Record) LiveRefresh ¶
LiveRefresh reports whether this renewable token is before both refresh and absolute expiry.
type RefreshRevocationBackend ¶
type RefreshRevocationBackend interface {
// RevokeRefresh removes the family matching a current or consumed refresh digest and
// returns its subject, omitting unknown families.
RevokeRefresh(context.Context, Address, Digest) (value.Optional[model.Identity], error)
}
RefreshRevocationBackend revokes the family that issued a refresh digest, whether it is the current or previous generation's or a consumed one, under the subject lock shared with issuance. It returns the removed family's subject, omitted when no family matches. Expired families are removed too.
type SelectiveBackend ¶
type SelectiveBackend interface {
// RevokeOthers removes every token family of the subject except keep, returning the
// count.
RevokeOthers(context.Context, Address, model.Identity, model.ID[Record]) (uint64, error)
}
SelectiveBackend revokes every family of a subject in this address except keep, under the subject lock shared with issuance, and returns the count.
type Store ¶
type Store struct {
// contains filtered or unexported fields
}
Store borrows a backend and shares bounded operation capacity across bindings. The application owns the backend pool's lifecycle.
type Ticket ¶
type Ticket[M, K any] struct { // contains filtered or unexported fields }
Ticket is a single-use handshake credential for the token family that authenticated its issuing request, for transports that cannot send an Authorization header, such as a browser WebSocket. Secret() is an explicit transport boundary; routine formatting and JSON never disclose it.
type TicketBackend ¶
type TicketBackend interface {
// IssueTicket stores a bounded single-use ticket for a live family and returns its
// expiry, omitting families that are no longer live.
IssueTicket(context.Context, Address, model.Identity, model.ID[Record], Digest, time.Duration, int) (value.Optional[temporal.DateTime], error)
// RedeemTicket atomically deletes and reads a ticket, omitting unknown or expired
// tickets.
RedeemTicket(context.Context, Address, Digest) (value.Optional[TicketRecord], error)
// LookupFamily returns a live family's current generation for revalidation.
LookupFamily(context.Context, Address, model.Identity, model.ID[Record]) (value.Optional[Record], error)
// PruneTickets removes at most limit expired tickets in the address.
PruneTickets(context.Context, Address, int) (uint64, error)
}
TicketBackend stores single-use handshake tickets as hashes. IssueTicket stores one for the subject's live family, first dropping that family's expired tickets and the oldest beyond max-1, and reports omitted expiry when the family is no longer live. RedeemTicket deletes the ticket in the statement that reads it, so a ticket redeems at most once; an unknown or expired ticket is omitted. Revoking, refreshing past or expiring a family never revives a ticket, and deleting a family deletes its tickets. LookupFamily reads a family's current generation for a re-check and is omitted unless the family is live. PruneTickets deletes at most limit expired tickets of the address.
type TicketRecord ¶
type TicketRecord struct {
Family model.ID[Record]
Subject model.Identity
ExpiresAt temporal.DateTime
}
TicketRecord is a redeemed ticket: the family and subject it was issued for.
type Tokens ¶
type Tokens[M model.Identifiable, K any] struct { // contains filtered or unexported fields }
Tokens binds one stored model/provider/guard/source and declared scope ceiling. Its guard is constructed once; persisted tokens cannot be rebound by extracting an unscoped strategy. Construction performs no I/O. It issues with the store's lifetimes unless WithLifetimes shortens them for this guard.
func New ¶
func New[M model.Identifiable, K any](store *Store, name auth.GuardName, provider auth.Provider[M, K], source auth.CredentialName, allowed auth.AccessScopes[M], opts ...Option) (*Tokens[M, K], error)
New binds a token store, provider, guard and credential source with an immutable allowed-scope ceiling and validated options.
func (*Tokens[M, K]) CompleteMFA ¶
func (t *Tokens[M, K]) CompleteMFA(ctx context.Context, raw secret.String, factor auth.SecondFactor[M, K], options IssueOptions[M]) (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 (*Tokens[M, K]) Current ¶
Current returns the metadata of the token that authenticated this guard in the current auth scope, including its effective scopes (for example to mark "this device" in List results by comparing IDs). It reuses the scope's verification; no second lookup runs.
func (*Tokens[M, K]) CurrentProof ¶
CurrentProof returns a proof for the current request's model that retains the presented token's scope grants. Issuing a token from it can only narrow those grants, unlike auth.NewProof, which is unrestricted.
func (*Tokens[M, K]) Guard ¶
Guard returns the token authentication guard, or an undefined guard for a nil binding.
func (*Tokens[M, K]) Issue ¶
func (t *Tokens[M, K]) Issue(ctx context.Context, proof auth.Proof[M, K], options IssueOptions[M]) (Issued[M, K], error)
Issue persists a trusted verified proof. It does not verify a password or a submitted identity. Requested scopes cannot exceed this binding's declaration or the input proof's grant. Pending MFA has fixed expiry and cannot refresh.
func (*Tokens[M, K]) IssueTicket ¶
IssueTicket mints a single-use ticket for the token family that authenticated this guard in the current request. Only its hash is stored. It expires after Config.TicketLifetime, the first redemption consumes it, and revoking the family deletes it. Mount it behind this binding's guard and deliver it through a no-store credential response. Only a TicketEndpoint.URL delivery boundary may put the single-use ticket in a URL; never put access or refresh tokens there. Redact ticket query parameters from ingress logs and use HTTPS.
func (*Tokens[M, K]) List ¶
func (t *Tokens[M, K]) List(ctx context.Context, reference model.Reference[M, K]) ([]Info[M, K], error)
List returns bounded current-family metadata. An expired access credential can still have a live refresh grant; callers can inspect both expiry values.
func (*Tokens[M, K]) Logout ¶
Logout revokes the family of a presented access token and reports EventLogout when it removed one.
func (*Tokens[M, K]) LogoutRefresh ¶
LogoutRefresh revokes the family of a presented refresh secret, for a logout authenticated by the refresh credential itself, such as a browser's HttpOnly refresh cookie: an expired access token does not prevent it. A current, previous or consumed refresh secret of the family revokes it, as replaying one would; an unknown one revokes nothing and is not an error, so logout stays idempotent. A malformed secret is Unauthenticated, as with Revoke. It reports EventLogout when it removed a family.
func (*Tokens[M, K]) Prune ¶
Prune removes at most limit expired families with their bounded generation history. Stable subject rows remain for issuance/revocation serialization.
func (*Tokens[M, K]) PruneExpired ¶
PruneExpired prunes expired token families of this guard in batches of batch families, stopping after a short batch or maxBatches, and reports the families removed. Schedule it from the application calendar or the configured housekeeping schedule; the auth package does not depend on the scheduler.
func (*Tokens[M, K]) RedeemTicket ¶
func (t *Tokens[M, K]) RedeemTicket(ctx context.Context, raw secret.String) (value.Optional[auth.BoundCredential], error)
RedeemTicket consumes a ticket issued by this binding. A redeemed ticket becomes a bound credential for TicketSource, which each later auth scope re-verifies against the live token family, its subject's current eligibility and the binding's scope ceiling. An unknown, expired or already redeemed ticket is omitted; the caller treats that as unauthenticated.
func (*Tokens[M, K]) Refresh ¶
Refresh consumes one renewable secret atomically. Reuse of a consumed secret revokes the entire family, including a concurrent successful successor. Clients must serialize refresh and reauthenticate after an uncertain/failed outcome; the framework never retries or returns partial credentials.
func (*Tokens[M, K]) Revocation ¶
func (t *Tokens[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 (*Tokens[M, K]) Revoke ¶
Revoke hashes the access credential and removes its family, reporting whether it existed.
func (*Tokens[M, K]) RevokeAll ¶
func (t *Tokens[M, K]) RevokeAll(ctx context.Context, reference model.Reference[M, K]) (uint64, error)
RevokeAll removes the reference's token families after checking provider ownership.
func (*Tokens[M, K]) RevokeAllIn ¶
func (t *Tokens[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 (*Tokens[M, K]) RevokeCurrent ¶
RevokeCurrent revokes the family of the token that authenticated this request (API logout on an authenticated route). It reports EventLogout when it removed the family.
func (*Tokens[M, K]) RevokeID ¶
func (t *Tokens[M, K]) RevokeID(ctx context.Context, reference model.Reference[M, K], id ID[M]) (bool, error)
RevokeID removes one family belonging to this exact model subject and guard. Authorize the caller before supplying a subject; the ID is not authority.
func (*Tokens[M, K]) RevokeOthers ¶
RevokeOthers revokes every other token family 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.
func (*Tokens[M, K]) TicketSource ¶
func (t *Tokens[M, K]) TicketSource() auth.CredentialName
TicketSource is the credential source that redeemed tickets authenticate: this binding's guard source.
func (*Tokens[M, K]) Touch ¶
Touch records explicit access activity without extending access, refresh or absolute expiry. Ordinary guard verification remains read-only.
func (*Tokens[M, K]) ValidateTickets ¶ added in v0.4.0
ValidateTickets checks the binding and whether its configured store supports enabled tickets, without acquiring resources or issuing a credential.
func (*Tokens[M, K]) WithObserver ¶
WithObserver returns a binding sharing this guard that reports EventLogin for full issuance (including MFA completion), EventLogout for Logout, LogoutRefresh and RevokeCurrent, and EventOtherDevicesLoggedOut for RevokeOthers.
type TransactionalBackend ¶
type TransactionalBackend interface {
// RevokeAllIn removes the subject's token families 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.