X Enterprises
fastify-xauth-jwks

requirePermission

Fastify preHandler factory that replies 403 if the authenticated user lacks the required permission.

requirePermission

Create a Fastify preHandler hook that enforces fine-grained permission-based access control. Returns 403 Forbidden if the authenticated user's permissions claim does not include at least one of the specified permissions.

Signature

import { requirePermission } from "@xenterprises/fastify-xauth-jwks/utils";

requirePermission(permissions: string | string[]): FastifyPreHandlerHook

Params

NameTypeRequiredDescription
permissionsstring | string[]YesPermission name or array of permission names. The user must have at least one of the specified permissions.

Returns

An async Fastify preHandler hook (request, reply) => Promise<void>. Replies with 403 { error: "Forbidden", message: "Insufficient permissions" } if the check fails.

Throws

Does not throw at call time. The returned handler does not throw — it replies with 403 instead.

Examples

Basic — require a specific write permission

import { requirePermission } from "@xenterprises/fastify-xauth-jwks/utils";

fastify.put("/admin/content/:id", {
  preHandler: requirePermission("content:write"),
  handler: async (request) => {
    const updated = await db.content.update(request.params.id, request.body);
    return updated;
  },
});

Realistic — multiple acceptable permissions, chained with role check

import { requireRole, requirePermission } from "@xenterprises/fastify-xauth-jwks/utils";

fastify.post("/admin/api-keys", {
  preHandler: [
    requireRole("admin"),
    requirePermission(["api-keys:create", "api-keys:manage"]),
  ],
  handler: async (request) => {
    const key = await db.apiKeys.create({
      userId: request.auth.userId,
      scopes: request.body.scopes,
    });
    return { apiKey: key.value };
  },
});

See Also

AI Context

package: "@xenterprises/fastify-xauth-jwks"
import: requirePermission from "@xenterprises/fastify-xauth-jwks/utils"
use-when: Fastify preHandler factory that returns 403 if the JWT payload lacks the specified permission
usage: { preHandler: [requirePermission(['read:documents'])] }
Copyright © 2026