Documentation
¶
Overview ¶
Package authn verifies the delegated human's identity. This is separate from - and a prerequisite for - the capability/reversibility machinery: every policy decision downstream trusts DelegatedUser/DelegatedRole, so those values must come from a signed token, never from a plain string the caller wrote into the request itself. Two modes behind one Verifier type: HS256 with a shared secret (local/dev, paired with cmd/devtoken), or RS256 against a real IdP's published JWKS (NewJWKSVerifier). Callers don't know which is active.
JWKS (RFC 7517) fetch/parse for real-IdP mode (Verifier.jwksURL set via NewJWKSVerifier). Hand-rolled against the stdlib rather than a third- party JWKS library, deliberately - this project already has an established pattern for exactly this shape of problem (fetch a set of public signing keys from a discovery endpoint, cache by id, refresh on demand) hand-rolled against stdlib crypto in internal/capability/keyring.go for the biscuit signing key, and the actual parsing needed here (base64url-decode an RSA modulus/exponent into a crypto/rsa.PublicKey) is small enough that pulling in a dependency for it isn't worth it on a security-critical verification path. RSA only (RS256/384/512) for now - what every major enterprise IdP (Okta, Auth0, Azure AD, Google) issues by default; an EC key in the document is skipped, not silently mistaken for something it isn't.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type Claims ¶
type Claims struct {
DelegatedUser string `json:"delegated_user"`
DelegatedRole string `json:"delegated_role"`
jwt.RegisteredClaims
}
type Verifier ¶
type Verifier struct {
// contains filtered or unexported fields
}
func NewJWKSVerifier ¶
NewJWKSVerifier is real-IdP mode: tokens are verified against RS256 keys fetched from jwksURL (RFC 7517), not a shared secret. issuer is mandatory, not optional - without issuer (and, when set, audience) validation, a token legitimately issued by the same IdP for a *different* application could be replayed against this proxy, a real cross-app token confusion risk, not a theoretical one. userClaim/ roleClaim let a real IdP's own claim names (Auth0's namespaced custom claims, Okta's custom authorization-server claims, an Azure AD app's optional claims - very unlikely to be named exactly "delegated_user"/ "delegated_role" out of the box) map onto this proxy's two required fields via config rather than code; empty defaults to those same two names, so an operator only sets these if their IdP actually differs.
Fetches the JWKS once, synchronously, before returning - an operator misconfiguring the URL should find out at startup, not on the first real login - then refreshes it in the background every 10 minutes, and additionally on-demand whenever a token names a "kid" not in the current cache (the same reasoning GET /biscuit-keys's own discovery endpoint uses: the IdP rotating its signing key should never require a synchronized manual update on this side).
func NewOpenVerifier ¶
NewOpenVerifier is zero-config mode's verifier (cmd/rinwall's --mcp flag): a request arriving with NO Authorization header is treated as the given local identity instead of being rejected, so getting started doesn't require minting a token first.
The narrowness matters. This makes a MISSING credential succeed; it does not make a BAD one succeed. A request that does present a token is verified exactly as strictly as ever, and a forged or expired one is still rejected rather than quietly falling back to the local identity - which would turn this convenience into a trivial authentication bypass. Two useful consequences: an operator can hand out real tokens to exercise role policy without restarting out of this mode, and approvals still require a genuine, distinct identity, so the self-approval check stays real.
cmd/rinwall only ever pairs this with a loopback-only listener - see its refusal to bind a non-local address in zero-config mode.
func NewVerifier ¶
func (*Verifier) FromRequest ¶
FromRequest extracts and verifies the bearer token from the standard Authorization header - the one place both adapters pull delegated identity from.
func (*Verifier) IsOpen ¶
IsOpen reports whether a missing credential is accepted, so callers can say so in a startup banner rather than leaving it implicit.
func (*Verifier) Verify ¶
Verify checks signature, expiry, and that the required delegated-identity claims are present. In ordinary (HS256) mode it deliberately does not accept "none" or any asymmetric algorithm switch - only the configured HMAC secret. In JWKS mode (see NewJWKSVerifier) it verifies against the discovered RS256 keys instead, and additionally enforces issuer (and audience, if configured).