Authenticate with Clerk
Protect the admin with Clerk and enforce a role from session claims.
This guide connects the existing Clerk session to FlowPanel and restricts the admin to users whose public metadata role is admin.
Prerequisites
Clerk must already work in the host Next.js application. Install its Next.js SDK if needed:
pnpm add @clerk/nextjsProtect the route with Clerk
Configure Clerk middleware using the same admin and API paths generated by FlowPanel. The middleware is the first authentication boundary; FlowPanel's server handlers remain the authorization boundary.
Wrap the root application in ClerkProvider according to the installed Clerk version. The complete maintained example is examples/with-clerk.
Configure FlowPanel auth
import { defineAdmin } from "@flowpanel/kit";
import { withClerk } from "@flowpanel/kit/auth";
export default defineAdmin({
adapter,
auth: withClerk({
requireRole: "admin",
signInUrl: "/sign-in",
forbiddenUrl: "/",
}),
resources,
});By default, withClerk reads publicMetadata.role and falls back to guest. It uses the Clerk user ID as the actor ID for audit and per-user rate limiting. Supply role or userId only when your claims use a different shape.
Put the role in the session
Set publicMetadata.role for the user and include public_metadata in the Clerk session token as publicMetadata. A database role that is not present in the session claims cannot be read by withClerk without a custom resolver.
Treat metadata changes as authentication state changes. Sign out and back in, or otherwise refresh the Clerk session, before testing a new role.
Verify the boundary
Test all three cases:
- no Clerk session: the admin page follows
signInUrl, while API requests are rejected; - signed in without
admin: the page followsforbiddenUrl, while API requests return forbidden; - signed in as
admin: the page and resource API succeed.
Also call one action route as a non-admin. A hidden button is not proof; the server response is.
Production notes and failure modes
withClerkthrows a clear startup/runtime error when@clerk/nextjsis absent.- Missing or misspelled public metadata resolves to
guestand should fail the role gate. - Keep API and stream paths inside the Clerk middleware matcher.
- Do not use
devAuth()or the generated session stub in production.
Continue with Roles and permissions. Exact options are generated in Configuration reference.