Documentation
¶
Overview ¶
Package auth handles authentication: it validates JWT Bearer tokens and records the caller's role, claims, and any token-validation error in the request context. It makes no authorization decisions and writes no HTTP responses — authorization lives in internal/policy (role checks) and the gates in internal/api (which translate decisions into HTTP responses).
Index ¶
- Variables
- func AuthErrorFromContext(ctx context.Context) error
- func ClaimsFromContext(ctx context.Context) (jwt.MapClaims, bool)
- func IsOperator(ctx context.Context) bool
- func RoleFromContext(ctx context.Context) string
- func WithAuthError(ctx context.Context, err error) context.Context
- func WithClaims(ctx context.Context, claims jwt.MapClaims) context.Context
- func WithOperator(ctx context.Context) context.Context
- func WithRole(ctx context.Context, role string) context.Context
- type Authenticator
- type Config
- type PolicySource
- type TenantSource
- type Wiring
Constants ¶
This section is empty.
Variables ¶
var ErrVerifierPending = errors.New("token verifier not ready: the tenant's JWKS has not been fetched yet")
ErrVerifierPending is the auth error stashed for a token that could not be checked because its tenant's JWKS has not been fetched yet — at boot, or after a reload changed the tenant's jwks_url or role_claim (either rebuilds the verifier, fetch included). Distinct from an invalid token on purpose: the token may well be good, so the tenant route answers 503 + Retry-After (api) rather than evaluate the request under the policy default_role, which could accept its data under a lesser role while another pod holding the keys would have served it properly.
Functions ¶
func AuthErrorFromContext ¶
AuthErrorFromContext returns the token-validation error recorded when a present token failed to validate (bad signature, malformed, expired). It is nil for a valid token or for no token at all. Gates use it to fail loud — surfacing the token problem instead of a bare "forbidden" — when a request that fell back to the default role is denied for lacking permission.
func ClaimsFromContext ¶
ClaimsFromContext extracts JWT claims from the request context. ok is false when no valid token established claims.
func IsOperator ¶
IsOperator reports whether the request was authenticated with the operator key. See WithOperator.
func RoleFromContext ¶
RoleFromContext extracts the role string from the request context. An empty string means no role was established — no token, a token without a role claim, or an invalid/expired token — which callers resolve to the policy default_role via policy.ResolveRole.
func WithAuthError ¶
WithAuthError returns a copy of ctx carrying a token-validation error, used by gates to fail loud when a request that fell back to the default role is denied. See AuthErrorFromContext.
func WithClaims ¶
WithClaims returns a copy of ctx carrying the given JWT claims. Set by the middleware; exported so tests (and any code constructing an authenticated context) can establish identity.
func WithOperator ¶
WithOperator returns a copy of ctx marked as a platform-operator request, set by the middleware when a valid operator key is presented (Authorization: Operator <key>, or the X-Operator-Key alias). The operator bit authorizes the admin surface independently of the policy — RequireAdmin honors it even when the policy is nil (policies.json empty) — so it is the break-glass path that keeps the admin surface reachable while locked out (trigger a reload after fixing the files).
Types ¶
type Authenticator ¶ added in v0.2.0
type Authenticator struct {
// contains filtered or unexported fields
}
Authenticator owns one verifier per tenant behind the middleware, so a settings reload can replace a tenant's without restarting: Reconfigure builds a new verifier from the tenant's adopted wiring and swaps it in when that wiring changed, keeping the one it has when it did not; Prune drops the verifiers of tenants that stopped being served, rejected or removed; Close stops every JWKS refresh. The operator key is boot config and never changes.
func NewAuthenticator ¶ added in v0.2.0
func NewAuthenticator(cfg Config, tenantOf TenantSource, policies PolicySource) *Authenticator
NewAuthenticator builds an Authenticator with no verifier yet: the caller adds one per tenant with Reconfigure. tenantOf names the request's tenant; nil reads every request as tenant.Default (a single-tenant test). policies backs the operator-key path (the admin role it stamps is the request tenant's) and may be nil when no operator key is configured.
func (*Authenticator) Close ¶ added in v0.2.0
func (a *Authenticator) Close()
Close stops every verifier's JWKS refresh. The middleware then fails closed for every tenant; it is not meant to be served past this.
func (*Authenticator) Middleware ¶ added in v0.2.0
func (a *Authenticator) Middleware() func(http.Handler) http.Handler
Middleware returns the http middleware bound to this Authenticator; it reads the request tenant's current verifier on every request.
func (*Authenticator) Prune ¶ added in v0.2.0
func (a *Authenticator) Prune(served func(tenant.ID) bool)
Prune drops the verifier of every tenant served does not vouch for — the tenants a reload removed or rejected — and stops their JWKS refresh: a tenant that is not being served has no work running for it, and one that is adopted again is rebuilt, fetch and all, by Reconfigure.
func (*Authenticator) Reconfigure ¶ added in v0.2.0
func (a *Authenticator) Reconfigure(id tenant.ID, w Wiring)
Reconfigure gives tenant id a verifier built from w, replacing the one it has when w changed — the adopted settings are the authority, so the swap does not depend on a JWKS fetch succeeding (see newVerifier) — and keeping it, refresh and all, when w did not. The replaced verifier's JWKS refresh is stopped.
type Config ¶
type Config struct {
// OperatorKey is the optional non-JWT operator credential; a match on
// the presented credential (Authorization: Operator <key>, or the
// X-Operator-Key alias) authorizes a full-access platform operator (see
// Middleware).
OperatorKey string
}
Config is the boot-config half of authentication: the platform's own credential, fixed for the process lifetime and shared by every tenant.
type PolicySource ¶ added in v0.2.0
PolicySource yields a tenant's access-control policy, read per request so a settings reload applies to the next one. nil for a tenant that is not being served — the ops tree over a nested directory with no tenant 0, where the gate reads no policy either.
type TenantSource ¶ added in v0.2.0
TenantSource names the tenant a request resolved to — the store api.TenantMW put in the context, and its Tenant() — and false on a tenant-exempt route, where none was resolved.
type Wiring ¶ added in v0.2.0
type Wiring struct {
JWKSURL string
// JWTSecret is the HMAC secret, the verifier when JWKSURL is empty; a
// tenant's own, so a reload that rotates it rebuilds the verifier.
JWTSecret string
RoleClaim string // dot-separated claim path, e.g. "role" or "app_metadata.role"
}
Wiring is one tenant's half: the verifier wiring its settings directory's auth block carries, adopted per tenant (Authenticator.Reconfigure).