Documentation
¶
Index ¶
Constants ¶
const ( // HeaderName is the HTTP header that carries the DPoP proof (RFC 9449 section 5). HeaderName = "DPoP" // NonceHeader is the HTTP response header carrying a fresh nonce (RFC 9449 section 8.3). NonceHeader = "DPoP-Nonce" // ErrorUseNonce signals the client to retry with a fresh nonce. ErrorUseNonce = "use_dpop_nonce" // ErrorInvalidProof signals a malformed, wrong, or replayed DPoP proof. ErrorInvalidProof = "invalid_dpop_proof" // ErrorInvalidBinding signals that the proof key does not match the access token's cnf.jkt. ErrorInvalidBinding = "invalid_token_binding" )
const ( DefaultProofMaxAge = 60 * time.Second DefaultFutureSkew = 60 * time.Second DefaultJtiTTL = 2 * time.Minute )
Validation timing parameters shared by every service that enforces DPoP.
Variables ¶
var ( ErrMissingProof = newError(ErrorUseNonce, http.StatusBadRequest, "DPoP proof is required") ErrMissingNonce = newError(ErrorUseNonce, http.StatusBadRequest, "missing DPoP nonce") ErrInvalidNonce = newError(ErrorUseNonce, http.StatusBadRequest, "invalid or expired DPoP nonce") ErrReplay = newError(ErrorInvalidProof, http.StatusBadRequest, "DPoP proof replay detected") )
Predefined validation failures. Missing proofs/nonces are signalled with the use_dpop_nonce code so the client can retry with a fresh nonce (RFC 9449 section 8.3).
Functions ¶
func RequestHTU ¶
RequestHTU reconstructs the client-facing request URI that a DPoP proof's htu must match, honoring the forwarded headers set by the gateway.
Types ¶
type NonceStore ¶
type NonceStore interface {
// ConsumeNonce atomically deletes the single-use nonce and reports whether
// it existed (false => missing, reused, or expired).
ConsumeNonce(ctx context.Context, nonce string) (bool, error)
// ReserveJti atomically records the proof jti for the given TTL and reports
// whether it was a brand-new value (false => replay detected).
ReserveJti(ctx context.Context, jti string, ttl time.Duration) (bool, error)
}
NonceStore provides single-use nonces and jti replay detection. Implemented by each service over its Redis client, keeping the shared package free of storage-library dependencies.
type Proof ¶
type Proof struct {
Raw string
Header proofHeader
Claims ProofClaims
Key *ecdsa.PublicKey
}
Proof is a parsed and validated-claim DPoP proof.
func ParseProof ¶
ParseProof parses a compact JWS proof and extracts the embedded public key.
func (*Proof) Thumbprint ¶
Thumbprint returns the RFC 7638 SHA-256 thumbprint (jkt) of the proof key.
func (*Proof) Validate ¶
func (p *Proof) Validate(method string, htu string, now time.Time, maxAge, futureSkew time.Duration) error
Validate checks the htm, htu, iat and jti claims of the proof against the request.
func (*Proof) VerifySignature ¶
VerifySignature verifies the JWS signature against the key embedded in the header.
type ProofClaims ¶
type ProofClaims struct {
Jti string `json:"jti"`
Htm string `json:"htm"`
Htu string `json:"htu"`
Iat int64 `json:"iat"`
Nonce string `json:"nonce,omitempty"`
}
ProofClaims are the registered claims of a DPoP proof (RFC 9449 section 4.2).
type Validator ¶
type Validator struct {
// NonceStore provides single-use nonces and jti replay detection. When nil,
// nonce and replay checks are skipped (not for production).
NonceStore NonceStore
// IssueNonce creates and persists a fresh single-use nonce.
IssueNonce func(ctx context.Context) (string, error)
ProofMaxAge time.Duration
FutureSkew time.Duration
JtiTTL time.Duration
}
Validator runs the complete RFC 9449 proof validation sequence shared by the protected-route middleware and the token-issuing endpoints, so behaviour is consistent everywhere.
func (*Validator) Validate ¶
Validate parses and validates the DPoP proof carried by r. On success it returns the proof and a fresh nonce to send back in the DPoP-Nonce response header. On failure it returns a *Error (along with a fresh nonce to challenge the client), or a plain error if the storage backend is unavailable.