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

token

package
v0.0.12 Latest Latest
Warning

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

Go to latest
Published: Sep 20, 2026 License: Apache-2.0, MIT Imports: 12 Imported by: 0

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

View Source
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

func Hash

func Hash(raw string) string

Hash derives the at-rest form of a raw token (SHA-256, base64url).

func NewRaw

func NewRaw() (string, error)

NewRaw draws a fresh opaque 256-bit token, base64url-encoded. Callers store token.Hash(raw) and deliver raw once.

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.

func (*PostgresStore) Consume

func (s *PostgresStore) Consume(ctx context.Context, tokenHash string) (*Token, error)

Consume deletes + returns the token for the hash; only an unexpired token resolves.

func (*PostgresStore) Upsert

func (s *PostgresStore) Upsert(ctx context.Context, token *Token) error

Upsert writes (or replaces) the single token per user+purpose and stamps last_sent_at.

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.

type Token

type Token struct {
	ID        string
	UserID    string
	TokenHash string
	CreatedAt time.Time
	ExpiresAt time.Time
	// LastSentAt tracks the most recent delivery for resend
	// throttling; nil when never sent.
	LastSentAt *time.Time
}

Token is one auth_tokens row. UserID is the bare UUID column form.

Jump to

Keyboard shortcuts

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