Documentation
¶
Overview ¶
Package token owns the shared one-shot token store (public.auth_tokens): rows keyed by (user_id, purpose), SHA-256 hash at rest, single-use consumption with an expiry check. Consumers (emailverification, onetimeaccess) scope a store with their purpose and keep their own sentinels/TTLs.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ErrNotFound = errors.New("token: invalid or expired")
ErrNotFound is returned by Consume for unknown, expired, or already-used tokens — indistinguishable by design. Consumers map it onto their own sentinel.
Functions ¶
Types ¶
type PostgresStore ¶
type PostgresStore struct {
// contains filtered or unexported fields
}
PostgresStore persists tokens in public.auth_tokens, scoped to one purpose per instance.
func NewStore ¶
func NewStore(exec datastore.Executor, purpose Purpose) *PostgresStore
NewStore builds the production store for one purpose.
type Purpose ¶
type Purpose string
Purpose discriminates the auth_tokens rows; values are stored verbatim (DB CHECK constrains them).
const ( // PurposeEmailVerification covers email verification links. PurposeEmailVerification Purpose = "email_verification" // PurposeOneTimeAccess covers one-time access sign-in tokens. PurposeOneTimeAccess Purpose = "one_time_access" // PurposeReauthentication exists in the DB CHECK but has no consumer yet. PurposeReauthentication Purpose = "reauthentication" // PurposePasswordReset covers forgot/reset password tokens. PurposePasswordReset Purpose = "password_reset" )
type Store ¶
type Store interface {
// Upsert writes (or replaces) the single token per user+purpose.
Upsert(ctx context.Context, token *Token) error
// Consume deletes + returns the token for the hash; only an
// unexpired token resolves.
Consume(ctx context.Context, tokenHash string) (*Token, error)
}
Store persists purpose-scoped tokens.