• v1.0.2 601e6a5144

    Rene Nochebuena released this 2026-05-18 14:16:42 -06:00 | 0 commits to main since this release

    v1.0.2

    code.nochebuena.dev/go/httpauth

    Overview

    v1.0.2 closes three gaps discovered during integration testing of RBAC-guarded
    endpoints: wildcard resource support in ClaimsPermissionProvider, exact numeric
    precision for math.MaxInt64 permission masks, and JSON-formatted error responses
    across the full httpauth-* middleware stack.

    No breaking changes. All v1.0.x consumers can upgrade with go get.

    What Changed Since v1.0.1

    Wildcard resource fallback in ClaimsPermissionProvider

    ResolveMask now checks the requested resource key first, then falls back to "*" if
    the resource is absent from the JWT masks claim:

    // JWT masks claim: {"*": 9223372036854775807}
    provider := httpauth.NewClaimsPermissionProvider("masks")
    mask, _ := provider.ResolveMask(ctx, uid, "any_resource") // returns MaxInt64 — wildcard hit
    

    This enables the ADMIN system role to carry a single wildcard entry and pass every
    endpoint guard without enumerating resources. Per-resource entries take precedence over
    "*" when both are present.

    json.Number precision for high-bit masks

    ResolveMask now handles three numeric types from JWT claims:

    Type Source math.MaxInt64 safe?
    int64 Go construction
    float64 Standard JWT parsing (no option) ✗ (rounds to 2^63)
    json.Number jwt.WithJSONNumber() ✓ (decimal string parse)

    httpauth-jwt v1.0.2 uses jwt.WithJSONNumber() in all Verify implementations,
    so the json.Number path is now active for all tokens in the standard stack.

    Unified JSON error bodies — WriteJSONError

    New exported function:

    func WriteJSONError(w http.ResponseWriter, status int, code, message string)
    

    Writes a structured JSON error body matching the httputil.Error format:
    Content-Type: application/json with body {"code":"...","message":"..."}.

    All three auth middlewares in the stack now use this function:

    Middleware Condition Status Code
    httpauth-jwt AuthMiddleware Missing/invalid/expired token 401 UNAUTHENTICATED
    EnrichmentMiddleware No uid in context 401 UNAUTHENTICATED
    EnrichmentMiddleware Enricher returns error 500 INTERNAL
    AuthzMiddleware No identity in context 401 UNAUTHENTICATED
    AuthzMiddleware Permission denied or provider error 403 PERMISSION_DENIED

    Previously all three used http.Error which writes text/plain. AuthzMiddleware
    also had the wrong code string UNAUTHORIZED instead of UNAUTHENTICATED.

    Dependency

    Added code.nochebuena.dev/go/xerrors v1.0.1 for the code constants.

    Migration

    No breaking changes.

    go get code.nochebuena.dev/go/httpauth@v1.0.2
    
    Downloads