Use when implementing authorization and access control for FrontMCP tools, resources, prompts, or skills, deciding who may invoke what. Covers the RBAC, ABAC, and ReBAC models and when to choose each; JWT claims mapping per identity provider (Auth0, Keycloak, Okta, Cognito, Frontegg); reusable named authority profiles; and custom authority evaluators for domain-specific policy. This is about who-can-do-what (permissions, roles, scopes), distinct from configuring auth modes and login (see frontmcp-config) and custom login UI (see frontmcp-auth-ui). Triggers: authorization, access control, RBAC, ABAC, ReBAC, permissions, roles, scopes, policy enforcement, JWT claims, restrict who can call a tool.
Install with Codex or Claude Copy this prompt, paste it into Codex, Claude, or another assistant, and let it review the skill page and install it for you.
A direct command skips the review prompt. Inspect the source before running it.
Use when implementing authorization and access control for FrontMCP tools, resources, prompts, or skills, deciding who may invoke what. Covers the RBAC, ABAC, and ReBAC models and when to choose each; JWT claims mapping per identity provider (Auth0, Keycloak, Okta, Cognito, Frontegg); reusable named authority profiles; and custom authority evaluators for domain-specific policy. This is about who-can-do-what (permissions, roles, scopes), distinct from configuring auth modes and login (see frontmcp-config) and custom login UI (see frontmcp-auth-ui). Triggers: authorization, access control, RBAC, ABAC, ReBAC, permissions, roles, scopes, policy enforcement, JWT claims, restrict who can call a tool.
Built-in RBAC/ABAC/ReBAC authorization system for FrontMCP entry types. Each flow has native checkEntryAuthorities and filterByAuthorities stages that enforce access control policies declared via the authorities field on entry decorators. Configured via @FrontMcp({ authorities: { claimsMapping, profiles, scopeMapping } }) — no plugin needed. Flow stages handle enforcement, and developers can hook into them with Will, Did, and Around decorators. Supports named profiles for reuse, JWT claims mapping for any identity provider, inline policies with roles/permissions/attributes/relationships, and composable combinators (allOf, anyOf, not).
When to Use This Skill
Must Use
Adding role-based or permission-based access control to tools, resources, prompts, or skills
Restricting MCP entry visibility based on the caller's JWT claims
Enforcing tenant isolation (ABAC) or relationship checks (ReBAC) on entries
Gating which skills a caller can discover and load (@Skill({ authorities }))
Recommended
Setting up a multi-tenant server where different tenants see different tools
Building an admin vs. user distinction across your MCP surface
Combining multiple authorization models (e.g., RBAC + ABAC) on the same entry
Skip When
You only need authentication (login/token validation) without authorization (see frontmcp-config / configure-auth)
You are building a public server with no access restrictions (use mode: 'public')
You need OAuth scopes at the transport level, not entry-level policies (see configure-auth-modes)
Decision: Use this skill whenever you need to control who can access which entries based on roles, permissions, attributes, or relationships.
CRITICAL: Ask About JWT Shape First
Before writing any authorities configuration, the coding agent MUST ask the developer:
"What identity provider (IdP) are you using, and what does your JWT payload look like? I need to know where roles, permissions, and tenant ID are located in the claims."
Why this matters: Every IdP places roles and permissions in different JWT claim paths. Auth0 uses namespaced URIs (), Keycloak nests them under , Okta uses , Cognito uses , and Frontegg uses flat /. Writing without knowing the actual token shape will produce silent authorization failures where every user is denied.
https://myapp.com/roles
realm_access.roles
groups
cognito:groups
roles
permissions
claimsMapping
What to collect before proceeding:
Identity provider name (Auth0, Keycloak, Okta, Cognito, Frontegg, custom)
A sample decoded JWT payload (redacted sensitive values)
The claim path for roles (e.g., realm_access.roles)
The claim path for permissions (e.g., permissions or scope)
The claim path for tenant/org ID if multi-tenant (e.g., org_id, tenantId)
See references/claims-mapping.md for IdP-specific claim paths.
Prerequisites
FrontMCP SDK installed (@frontmcp/sdk)
@frontmcp/auth available (peer dependency of SDK, provides all authorities types)
An authentication mode configured (see frontmcp-config / configure-auth-modes) so that authInfo is populated on incoming requests
Knowledge of the developer's JWT token structure (see critical section above)
Steps
Step 1: Add the Authorities Config
Add the authorities field to your @FrontMcp decorator. No plugin import needed — authorities is a built-in framework feature.
Set claimsMapping to tell the engine where roles, permissions, and user/tenant identifiers live in your IdP's JWT. Each value is a dot-path into the decoded JWT claims object.
The OAuth-scopes-as-roles fallback means a token with no roles claim but with scope: "admin read" will be treated as having roles: ['admin', 'read']. Configure explicit claimsMapping.roles to opt out. For non-standard token shapes, use claimsResolver instead (see Common Patterns below).
Step 3: Register Named Profiles
Profiles let you define reusable authorization policies and reference them by name in decorators. Register them in the profiles field.
For dynamic, async authorization that does not warrant a reusable custom evaluator, use the
guards field. Each guard receives the same AuthoritiesEvaluationContext and returns
true on grant, or false/a denial string on deny. Guards run in sequence and combine with
other policy fields via operator (default AND).
Use guards for one-off async checks; promote to a registered custom evaluator when the
same logic is reused across many entries (see references/custom-evaluators.md).
Optional: Map Denials to OAuth Scope Challenges (scopeMapping)
If your transport layer issues OAuth scope challenges (RFC 6750 insufficient_scope),
declare a scopeMapping so authority denials are converted into the right WWW-Authenticate
challenge with the required scopes. Mapping is explicit only — no automatic
permission-to-scope inference.
pipes are functions that run during auth context construction and merge their output into
FrontMcpAuthContext. Use them to extract custom typed fields from JWT claims so they are
available to your tools as strongly typed accessors. Declare the resulting fields by
augmenting ExtendFrontMcpAuthContext:
A pipe receives the raw JWT claims (a Readonly<Record<string, unknown>>) and
returns a Partial<ExtendFrontMcpAuthContext> (sync or async). It does not
receive the AuthInfo envelope — there is no .user accessor on the input.
authorities on @Skill is enforced exactly like the other entry types, across
every surface a skill is served from:
Deny on load/read — loading a gated skill the caller can't access throws
AuthorityDeniedError (MCP code -32003), the same as a denied tools/call.
Covers skills/load (MCP), skill://<path>/SKILL.md and skill://<path>/<file>
reads (SEP-2640), and GET /skills/{id} (HTTP).
Filter on discovery — gated skills the caller can't access are removed from
skills/search / skills/list (MCP), the skill://index.json discovery index and
skill-path autocomplete (SEP-2640), and GET /skills (HTTP).
@Skill({ name: 'review-pr', description: '…', instructions: '…' }) // open to all@Skill({ name: 'internal-runbook', description: '…', instructions: '…',
authorities: 'admin' }) // admins only
Two limitations to design around:
List-time filtering is role/permission/claims-only. Discovery runs without
request input, so { fromInput: '…' } ABAC/ReBAC policies can't be evaluated when
filtering and will hide the skill from discovery. Use role/permission/claims
authorities for discoverable skills; input-dependent policies still enforce at
load time. (Same limitation applies to tools/resources/prompts.)
HTTP skills discovery is fail-closed. The Skills HTTP API uses a binary
api-key/bearer gate with no claims, so gated skills are hidden from GET /skills
and denied on GET /skills/{id} regardless of the bearer. Serve gated skills over
an MCP transport for claims-based access. Ungated skills are unaffected.
Boot-time fail-fast covers skills too: a @Skill with authorities but no configured
authorities engine fails server startup with AuthConfigurationError, exactly like a
tool/resource/prompt/agent.
FrontMcpAuthorityProfiles is augmented for type-safe profile references
@frontmcp/auth is imported so the authorities field is available on decorators
Troubleshooting
Problem
Cause
Solution
profile 'admin' is not registered
Profile used in decorator but not in authorities.profiles config
Add the profile to the profiles field in @FrontMcp({ authorities })
All users denied despite correct roles
claimsMapping.roles path does not match the actual JWT claim path
Decode a real JWT and verify the dot-path resolves to the roles array
authorities field not recognized on decorator
@frontmcp/auth not imported (metadata augmentation not active)
Add import '@frontmcp/auth' (or import type ... from '@frontmcp/auth') anywhere in your project to activate the metadata augmentation. There is no @frontmcp/auth/authorities subpath.
ABAC condition always fails
{ fromInput: 'tenantId' } but tool input field is named tenant_id
The fromInput key must exactly match the tool's input schema field name
ReBAC always denies
No relationshipResolver provided
Implement RelationshipResolver and pass it to plugin options
Custom evaluator not found
Key in custom.* policy does not match registered evaluator name
Ensure the evaluator is registered with the same key used in the policy
List endpoints show all entries
No authorities config in @FrontMcp() or hook priority conflict
Verify authorities: { ... } is set on @FrontMcp() decorator
AuthorityDeniedError has no detail
deniedBy field shows generic message
Check the evaluatedPolicies array on the error for which policy type failed
TS error: evaluators/relationshipResolver/claimsResolver not on AuthoritiesConfig
The runtime Zod schema accepts these keys but the exported AuthoritiesConfig interface in authorities.profiles.ts only declares claimsMapping, profiles, scopeMapping, pipes.
Pass the config inline (TS infers from the decorator's broader type) or cast the typed config as the interface catches up.
Examples
This skill currently exposes only references; see references/ for guidance.
Accessing This Skill
Skills are distributed as plain SKILL.md files plus a sibling references/
and examples/ tree, so consumers can pick whichever access mode fits:
Mode
How it works
Filesystem
Read libs/skills/catalog/frontmcp-authorities/ directly from a clone of the catalog repo, or from a published @frontmcp/skills install. SKILL.md is the entry point.
frontmcp CLI
frontmcp skills list, frontmcp skills read frontmcp-authorities, frontmcp skills read frontmcp-authorities:references/<file>.md, frontmcp skills install frontmcp-authorities — no server required.
MCP skill://
When a developer mounts this skill into their own FrontMCP server (@FrontMcp({ skills: [...] })), the SDK exposes it via SEP-2640 resources: skill://frontmcp-authorities/SKILL.md, skill://frontmcp-authorities/references/{file}.md, etc. The server’s skill://index.json returns the SEP-2640 discovery document for everything mounted on it.
The catalog itself is not an MCP server. The skill:// URIs only resolve
when a server has been configured to host this skill.
Reference
Auth Architecture — Full three-layer model: server auth, auth providers, authorities, vault, scope challenges