• v0.9.0 d1de096c72

    Rene Nochebuena released this 2026-03-19 07:46:31 -06:00 | 0 commits to main since this release

    v0.9.0

    code.nochebuena.dev/go/httpauth-firebase

    Overview

    httpauth-firebase provides three composable net/http middleware functions that
    implement the full Firebase authentication and authorization stack for HTTP services.
    The output contract is always rbac.Identity — downstream handlers and business
    logic are completely decoupled from Firebase types.

    This release reflects an API designed through multiple architecture reviews and
    validated end-to-end via the todo-api POC. It is versioned at v0.9.0 rather than
    v1.0.0 because it has not yet been exercised in production workloads across all edge
    cases, preserving the option for minor API refinements before committing to full
    stability.

    What's Included

    AuthMiddleware(verifier TokenVerifier, publicPaths []string) func(http.Handler) http.Handler

    Verifies the Authorization: Bearer <token> header via Firebase JWT verification
    and injects the uid and raw claims into the request context. Requests matching any
    pattern in publicPaths are passed through without token verification. Returns 401
    on missing or invalid tokens.

    EnrichmentMiddleware(enricher IdentityEnricher, opts ...EnrichOpt) func(http.Handler) http.Handler

    Reads the uid and claims injected by AuthMiddleware, calls the application-provided
    IdentityEnricher, and stores the resulting rbac.Identity in context via
    rbac.SetInContext. Supports an optional tenant header via WithTenantHeader. Returns
    401 if AuthMiddleware did not run upstream; returns 500 if the enricher fails.

    AuthzMiddleware(provider PermissionProvider, resource string, required rbac.Permission) func(http.Handler) http.Handler

    Reads rbac.Identity from context (set by EnrichmentMiddleware), resolves the
    permission mask via the application-provided 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 errors.

    Interfaces

    • TokenVerifier — abstracts *auth.Client for unit-test mockability; production code passes the Firebase auth client directly
    • IdentityEnricher — application-implemented; receives uid and raw claims, returns rbac.Identity
    • PermissionProvider — application-implemented; receives uid and resource name, returns rbac.PermissionMask

    Options

    • WithTenantHeader(header string) EnrichOpt — reads a tenant ID from a named request header and attaches it to the identity

    Installation

    go get code.nochebuena.dev/go/httpauth-firebase@v0.9.0
    

    Requires code.nochebuena.dev/go/rbac and firebase.google.com/go/v4.

    Design Highlights

    Provider-specific naming. The module is named httpauth-firebase because it
    imports the Firebase SDK directly. Other auth providers (Auth0, JWKS, etc.) live in
    sibling modules that all converge on the same rbac.Identity output contract. This
    leaves the door open for httpauth-auth0 or httpauth-jwt without naming conflicts.

    Three composable middleware, not one monolith. AuthMiddleware, EnrichmentMiddleware,
    and AuthzMiddleware are separate functions. Each can be applied independently at the
    router level or on individual route groups. A webhook endpoint might use only
    AuthMiddleware; a protected CRUD resource uses all three.

    rbac.Identity as the only output contract. Once EnrichmentMiddleware runs,
    downstream code reads identity exclusively via rbac.FromContext. No Firebase type
    leaks past the middleware boundary.

    No logger dependency. Errors are returned as HTTP responses. The module does not
    accept a logger parameter, keeping its dependency surface minimal.

    Glob-based public path bypass. Public paths use path.Match patterns (* wildcard
    supported), applied per request before any token parsing occurs.

    Known Limitations & Edge Cases

    • publicPaths matching uses path.Match (glob only). Regular expressions and
      prefix matching are not supported. A path like /api/v1/public/* requires an
      explicit * at the end; /api/v1/public does not match /api/v1/public/foo.
    • No refresh token handling. Revoked tokens are detected via
      VerifyIDTokenAndCheckRevoked, but the middleware does not issue or refresh tokens.
    • No claims caching. IdentityEnricher.Enrich is called on every request. Applications
      with expensive enrichment (e.g., database lookups) should implement their own caching
      inside the enricher.
    • EnrichmentMiddleware returns a generic 500 if the enricher fails; the specific error
      is not surfaced to the client. Log the error inside your enricher implementation.
    • AuthzMiddleware treats both provider errors and permission-check failures as 403.
      The two cases are intentionally indistinguishable to callers.

    v0.9.0 → v1.0.0 Roadmap

    • Evaluate whether publicPaths should support prefix matching in addition to glob patterns
    • Add an optional error hook or logger interface so enricher/provider errors can be observed without coupling to a specific logger
    • Consider claims caching support (e.g., an optional IdentityCache interface) for high-throughput services
    • Validate behavior under token revocation race conditions
    • Production hardening across multiple deployed services
    Downloads