dpop

package
v1.18.0 Latest Latest
Warning

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

Go to latest
Published: Oct 10, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package dpop verifies the ES256/P-256 profile of RFC 9449 sender proofs. Proofs establish possession of a key, never user identity or authorization.

Index

Constants

View Source
const NonceLifetime = 5 * time.Minute

NonceLifetime is how long a server nonce stays current.

Variables

View Source
var (
	ErrInvalidProof      = errors.New("invalid DPoP proof")
	ErrReplay            = errors.New("DPoP proof already used")
	ErrReplayUnavailable = errors.New("DPoP replay protection unavailable")
	// ErrNonceRequired refuses an otherwise valid proof without a current
	// server nonce (RFC 9449 §8); the client retries with a fresh one.
	ErrNonceRequired = errors.New("DPoP nonce required")
)

Functions

func Verify added in v1.5.0

func Verify(r *http.Request, c Check) (string, error)

Verify verifies exactly one DPoP header against c and the request method, and returns the proof key's RFC 7638 thumbprint (unpadded base64url). Call only after authenticating the access token.

Types

type Check added in v1.5.0

type Check struct {
	// URL is the trusted request URL: from server configuration or trusted
	// routing, never unvalidated forwarding headers.
	URL string
	// AccessToken is the token the proof must hash (ath); "" at a token
	// endpoint, where a proof carries none.
	AccessToken string
	// Thumbprint is the bound token's cnf.jkt; "" binds a new token to the
	// proof's key.
	Thumbprint string
	Replay     ReplayGuard
	// Nonces, when set, requires a current server nonce.
	Nonces NonceSource
}

Check is what a proof must match.

type NonceSource added in v1.18.0

type NonceSource interface {
	// Issue is a nonce current from now.
	Issue(ctx context.Context) string
	// Valid reports whether nonce is current.
	Valid(ctx context.Context, nonce string) bool
}

NonceSource issues server nonces and checks them (RFC 9449 §8 at a token endpoint, §9 at a resource server).

type Nonces added in v1.5.0

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

Nonces issues and checks RFC 9449 §8 server nonces without state: a nonce is its issue time and an HMAC of it under a key every replica shares. Replay is still the replay guard's job; a nonce bounds how far ahead a proof can be made.

func NewNonces added in v1.5.0

func NewNonces(key []byte) (*Nonces, error)

NewNonces keys nonces with key, at least 32 random bytes.

func (*Nonces) Issue added in v1.5.0

func (n *Nonces) Issue(context.Context) string

Issue is a nonce current from now.

func (*Nonces) Valid added in v1.5.0

func (n *Nonces) Valid(_ context.Context, nonce string) bool

Valid reports whether nonce was issued under this key within NonceLifetime.

type ReplayGuard

type ReplayGuard func(ctx context.Context, key string, ttl time.Duration) (bool, error)

ReplayGuard atomically claims key until ttl elapses. It returns true only for the first claim. All receiver replicas must share the same store. Errors must fail closed; implementations must not evict live claims to admit others. Keys are fixed-size SHA-256 digests; ttl is at most 121 seconds.

type Replays added in v1.17.0

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

Replays records spent single-use proofs (DPoP proofs, JWT-bearer assertions) until they expire: in Redis when given, shared by every replica, else in this process's memory (one node), which also takes over while Redis fails. Never PostgreSQL.

func NewReplays added in v1.17.0

func NewReplays(rdb redis.UniversalClient) *Replays

NewReplays spends proofs in rdb, or in memory when rdb is nil.

func (*Replays) Claim added in v1.17.0

func (r *Replays) Claim(ctx context.Context, key string, ttl time.Duration) (bool, error)

Claim is a ReplayGuard: it records key as spent for ttl, and reports false when it already was.

type StoredNonces added in v1.18.0

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

StoredNonces are random server nonces kept for NonceLifetime: in Redis when given, shared by every replica, else in this process's memory (one node), which also takes over while Redis fails. No key is configured. A nonce lost with its store fails once; the client retries with the fresh one.

func NewStoredNonces added in v1.18.0

func NewStoredNonces(rdb redis.UniversalClient) *StoredNonces

NewStoredNonces keeps nonces in rdb, or in memory when rdb is nil.

func (*StoredNonces) Issue added in v1.18.0

func (n *StoredNonces) Issue(ctx context.Context) string

Issue records a new random nonce.

func (*StoredNonces) Valid added in v1.18.0

func (n *StoredNonces) Valid(ctx context.Context, nonce string) bool

Valid reports whether nonce was issued and is current.

Jump to

Keyboard shortcuts

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