Documentation
¶
Overview ¶
Package http provides the resource-server middleware. Wraps an http.Handler in cap verification: read Authorization: Cap <b64>, decode, run capauth.Verifier.Verify against the static config, inject the verified identity onto the request context.
Audience naming: "<service>.<env>.<domain>", hashed to 32 bytes via cap.Hash32 before becoming the Verifier's Identity field. Resource servers compute the hash once at boot.
Scope naming: "<service>:<resource>:<action>", mapped to a 64-bit permission bitmask via the same scopeBit table the IAM controller uses (each service exports its own subset of the table — there's one canonical mapping per kind, in capabilities_kinds.md). The middleware caller supplies the required-bitmask as a uint64, not a scope string, because the bit math is the only thing the verifier knows.
Error envelope: failures write a tight JSON envelope. The cap itself is binary on the wire (Authorization: Cap <b64>); the error JSON is the HTTP-edge response. No /api/ prefix, no v2 — one canonical surface.
Index ¶
Constants ¶
This section is empty.
Variables ¶
var CapContextKey = &contextKey{name: "capauth.Cap"}
CapContextKey stashes the raw cap.Cap for handlers that need cap-typed fields (Audience, Caveats, etc.).
var ( // IdentityContextKey is the request-context key under which the // middleware stashes the verified Identity. Handlers read it with // `idt, ok := r.Context().Value(IdentityContextKey).(*capauth.Identity)`. IdentityContextKey = &contextKey{name: "capauth.Identity"} )
Functions ¶
func CapFromContext ¶
CapFromContext returns the raw cap.Cap stashed by the middleware. Used by handlers that need to attenuate the cap before calling a downstream service.
func FromContext ¶
func FromContext(ctx context.Context) (*capauth.IdentityCtx, bool)
FromContext is the typed accessor handlers use to fetch the verified identity from a request context. Returns (nil, false) on absence so callers can branch on auth state explicitly.
func Middleware ¶
Middleware returns an http.Handler middleware that verifies an Authorization: Cap <base64> header against the supplied Verifier configuration before calling next.
On success: the verified cap.Cap and an *Identity are stashed on the request context (via CapContextKey and IdentityContextKey respectively) and next is called.
On failure: a JSON error envelope is written with the appropriate status and next is NOT called.
Types ¶
type Config ¶
type Config struct {
// Verifier is the configured cap.Verifier. Build with
// capauth.LibVerifier{Store, Registry, Clock, Identity} once at boot.
// MUST set Identity to cap.Hash32([]byte(<service.env.domain>)) so
// the audience check is meaningful.
Verifier *capauth.LibVerifier
// AudienceHash is the hash of the resource-server's audience identifier.
// Identical to Verifier.Identity but kept on the Config for symmetry
// with the params the caller is passing in.
AudienceHash [32]byte
// RequiredScopeBits is the permission bitmask the request requires.
// Bits are derived from the canonical scope->bit table in the
// capabilities_kinds.md spec; the resource server is expected to know
// which bits map to which routes (per-route gating is the caller's job
// — this middleware checks one bitmask for all routes it wraps).
RequiredScopeBits uint64
// RequiredOp, if set, is an alternate way to express the required
// bits — semantically the same as RequiredScopeBits; named so handlers
// can be expressive about "what operation is this caller about to
// perform". The middleware ORs the two; either source of bits counts.
RequiredOp uint64
// ErrorWriter, if set, overrides the default JSON error writer. The
// default writes a tight {"error","error_description"} envelope and
// sets WWW-Authenticate on 401.
ErrorWriter func(w http.ResponseWriter, r *http.Request, status int, code, desc string)
}
Config drives the middleware. All fields are required.
type Identity ¶
type Identity = capauth.IdentityCtx
Identity is what the middleware hands the handler after a successful verification. The principal is the holder hex; scopes is the resolved permission bitmask plus the original scope strings (passed through); chain depth is len(chain)+1, useful for logging.
Importantly, this is the IDENTITY of the caller — not the cap itself. Handlers that need cap-typed fields (the cap.Cap, e.g., to attenuate before calling downstream) can pull the cap from the context too via CapContextKey.