Files
httpauth/CHANGELOG.md
Rene Nochebuena 18e5a16f7e feat(httpauth): initial release — provider-agnostic HTTP auth middleware
Provides SetTokenData for upstream AuthMiddleware implementations,
EnrichmentMiddleware and AuthzMiddleware compatible with any provider that
calls SetTokenData, ClaimsPermissionProvider for JWT-embedded permissions,
and CachedPermissionProvider for TTL-backed runtime resolution via any
Cache implementation.
2026-05-07 21:37:25 -06:00

4.0 KiB

Changelog

All notable changes to this module will be documented in this file.

The format is based on Keep a Changelog, and this module adheres to Semantic Versioning.

0.1.0 - 2026-05-08

Added

  • SetTokenData(ctx, uid, claims) context.Context — injects verified uid and raw claims into the request context; called by provider-specific AuthMiddleware implementations (e.g. httpauth-firebase, httpauth-jwt) after token verification; downstream middleware reads these values via unexported helpers in the same package
  • IdentityEnricher interface — application-implemented; receives uid string and claims map[string]any, returns rbac.Identity; called by EnrichmentMiddleware on every authenticated request
  • EnrichOpt functional option type for configuring EnrichmentMiddleware
  • WithTenantHeader(header string) EnrichOpt — reads a tenant ID from the named request header and attaches it to the identity via rbac.Identity.WithTenant; absent header leaves TenantID as an empty string with no error
  • EnrichmentMiddleware(enricher IdentityEnricher, opts ...EnrichOpt) func(http.Handler) http.Handler — reads uid and claims stored by any upstream AuthMiddleware via SetTokenData, calls enricher.Enrich, and stores the resulting rbac.Identity in context via rbac.SetInContext; returns 401 if no uid is present; returns 500 if the enricher fails
  • AuthzMiddleware(provider rbac.PermissionProvider, resource string, required rbac.Permission) func(http.Handler) http.Handler — reads rbac.Identity from context via rbac.FromContext, resolves the permission mask via the provided rbac.PermissionProvider, and gates the request against the required permission bit; returns 401 if no identity is in context; returns 403 if the permission check fails or the provider returns an error; uses rbac.PermissionProvider directly without redefining it
  • Cache interface — abstracts the caching backend for permission masks; Get(ctx, key) (int64, bool, error) and Set(ctx, key, value, ttl) error; implementations are typically backed by Valkey or Redis
  • NewCachedPermissionProvider(inner rbac.PermissionProvider, cache Cache, ttl time.Duration) rbac.PermissionProvider — wraps any rbac.PermissionProvider with a TTL-based cache layer; cache key format is rbac:{uid}:{resource}; on cache miss falls through to inner and populates the cache; on cache error falls through silently — never fails due to cache unavailability
  • NewClaimsPermissionProvider(claimsKey string) rbac.PermissionProvider — reads pre-computed permission masks from JWT claims stored in the request context by SetTokenData; expects claims[claimsKey] to be a map[string]any where each key is a resource name and the value is the bitmask as int64 or float64 (JSON decodes numbers as float64); returns 0 without error if the claim is absent

Design Notes

  • AuthzMiddleware uses rbac.PermissionProvider directly rather than redefining a local interface; rbac is the single source of truth for this contract
  • EnrichmentMiddleware and AuthzMiddleware are provider-agnostic — they depend only on SetTokenData having been called upstream; any AuthMiddleware that calls SetTokenData (Firebase, JWT, API key, etc.) is compatible without changes to the enrichment or authorization layer
  • Two rbac.PermissionProvider implementations ship with this module for the two common architectures: ClaimsPermissionProvider for simple applications that embed permissions in the JWT (no per-request DB or network call), and CachedPermissionProvider for applications where the permission set is too large to embed or needs to be independently revocable
  • CachedPermissionProvider uses TTL-based expiry exclusively; explicit invalidation is left to callers who can interact with the Cache directly using the rbac:{uid}:{resource} key format