fix(httpauth): wildcard resource fallback, json.Number precision, xerrors JSON error bodies
ClaimsPermissionProvider.ResolveMask now falls back to the "*" resource key when the
exact resource is absent in the JWT masks claim. Specific resource takes precedence;
wildcard is the fallback. Enables ADMIN wildcard masks ({"*": MaxInt64}) to pass every
endpoint guard without per-resource entries.
Add json.Number handling alongside existing int64/float64 paths. json.Number is
produced by jwt.WithJSONNumber() (httpauth-jwt) and preserves math.MaxInt64 exactly —
float64 would round to 2^63 and overflow on cast back to int64.
Export WriteJSONError(w, status, code, message) — shared JSON error helper for all
httpauth-* provider packages. Ensures a consistent {"code":"...","message":"..."} body
and Content-Type: application/json across the full middleware stack.
AuthzMiddleware and EnrichmentMiddleware now use WriteJSONError with xerrors code
constants (UNAUTHENTICATED, PERMISSION_DENIED, INTERNAL) instead of http.Error which
writes text/plain. AuthzMiddleware also fixes a wrong code string: UNAUTHORIZED →
UNAUTHENTICATED (stable gRPC-aligned name, matching xerrors.ErrUnauthorized).
Add xerrors v1.0.1 as a direct dependency for the code constants.
This commit is contained in:
@@ -2,6 +2,7 @@ package httpauth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
|
||||
"code.nochebuena.dev/go/rbac"
|
||||
)
|
||||
@@ -25,15 +26,24 @@ func (p *claimsPermissionProvider) ResolveMask(ctx context.Context, _, resource
|
||||
if !ok {
|
||||
return 0, nil
|
||||
}
|
||||
permisos, ok := claims[p.claimsKey].(map[string]any)
|
||||
masks, ok := claims[p.claimsKey].(map[string]any)
|
||||
if !ok {
|
||||
return 0, nil
|
||||
}
|
||||
switch v := permisos[resource].(type) {
|
||||
case int64:
|
||||
return rbac.PermissionMask(v), nil
|
||||
case float64:
|
||||
return rbac.PermissionMask(int64(v)), nil
|
||||
// Check specific resource first, then wildcard fallback.
|
||||
for _, key := range []string{resource, "*"} {
|
||||
switch v := masks[key].(type) {
|
||||
case int64:
|
||||
return rbac.PermissionMask(v), nil
|
||||
case float64:
|
||||
return rbac.PermissionMask(int64(v)), nil
|
||||
case json.Number:
|
||||
n, err := v.Int64()
|
||||
if err != nil {
|
||||
return 0, nil
|
||||
}
|
||||
return rbac.PermissionMask(n), nil
|
||||
}
|
||||
}
|
||||
return 0, nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user