package httpauth import ( "context" "net/http" "code.nochebuena.dev/go/rbac" ) // PermissionProvider resolves the permission mask for a given uid on a resource. type PermissionProvider interface { ResolveMask(ctx context.Context, uid, resource string) (rbac.PermissionMask, error) } // AuthzMiddleware reads the rbac.Identity from context (set by EnrichmentMiddleware) // and gates the request against the required permission on resource. // Returns 401 if no identity is in the context. // Returns 403 if the identity lacks the required permission or if the provider errors. func AuthzMiddleware(provider PermissionProvider, resource string, required rbac.Permission) func(http.Handler) http.Handler { return func(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { identity, ok := rbac.FromContext(r.Context()) if !ok { http.Error(w, "unauthorized", http.StatusUnauthorized) return } mask, err := provider.ResolveMask(r.Context(), identity.UID, resource) if err != nil || !mask.Has(required) { http.Error(w, "forbidden", http.StatusForbidden) return } next.ServeHTTP(w, r) }) } }