Scopes on Resources

API Resources use OAuth scopes tied to Role-Based Access Control (RBAC). MCP Server Resources use MCP OAuth scopes that can map to Connection scopes when tools need external credentials.

For how OAuth clients request these scopes, see Inbound Apps (APIs) and Agentic clients (MCP).

For controlling which clients can receive which scopes, see Policies.

API Resources

API Resources define the permission catalog for a protected API:

  • Scopes — What a client may do on the API (contacts.read, orders.write). These appear in the token's scope claim and are what you typically enforce per route.
  • Roles — Descope RBAC roles mapped to each scope. Roles carry permissions your backend may already understand. When a scope is granted, the mapped role(s) can appear in the token's roles claim so APIs can authorize from roles/permissions instead of maintaining a separate OAuth-scope map.

Permission scopes

FieldDescription
NameScope string in authorize/token requests and in the scope claim (e.g. shipments.read)
DescriptionShown on consent screens when an Inbound App requests access
RolesRBAC roles associated with this scope

Define roles and permissions under Authorization → RBAC, or via Management SDKs. Assign roles to users in the users table, through SSO group mapping, or programmatically.

How scope ↔ role mapping works

On an API Resource, each permission scope can be linked to one or more Descope roles. That mapping does two related jobs:

  1. Eligibility (user-delegated flows) — A user can only consent to (and receive) a scope if they hold at least one of the roles mapped to that scope (or otherwise satisfy RBAC for it).
  2. Token claims — When a scope is granted on a Resource access token, Descope includes the roles mapped to that granted scope in the token's roles claim (see User-delegated vs M2M below).

So if scope orders.write is mapped to role Order Editor, a token that includes orders.write can also include "roles": ["Order Editor"]. Your API can then resolve permissions under Order Editor the same way it does for first-party sessions, instead of hard-coding every OAuth scope in the backend.

ClaimMeaning
scopeSpace-separated OAuth scopes granted for this Resource
rolesRoles tied to those granted scopes (not necessarily every role the user or client has elsewhere)
audResource identifier (and any default audience values)
{
  "sub": "user123",
  "aud": ["https://api.example.com"],
  "scope": "contacts.write",
  "roles": ["Sales Manager"]
}

User-delegated (Authorization Code and CIBA)

Interactive grants (authorization code, CIBA) involve a user who authenticates and consents.

StepWhat happens
1. RequestThe client requests scopes (and usually a Resource via resource).
2. PolicyPolicies filter which scopes this client/user may receive. Scopes no policy allows are removed from the consent screen before the user sees them.
3. ConsentThe user can only approve scopes they are role-eligible for (roles mapped on the Resource). Scopes marked Allow user to decline scope can be declined; the rest must be accepted.
4. TokenThe access token includes granted scope values and the roles mapped to those granted scopes, even if the client requested more. See What Ends Up in the Token.

Important details:

  • roles mirrors granted scopes, not the user's full role set. If the user holds Admin, Sales Manager, and Sales Rep, but only consents to contacts.read (mapped to Sales Rep), the Resource token typically includes roles: ["Sales Rep"]—not every role on the user.
  • If the user lacks a required role for a scope, they cannot consent to that scope and it will not appear on the token.
  • Consent accumulates. There is one consent record per user per app or client, and newly granted scopes are added to it rather than replacing earlier ones. A user who consented to contacts.read and later to contacts.write holds both, so a later request for contacts.read alone issues a token without prompting again. See How Consent Accumulates.
  • To put all of the user's tenants, roles, and permissions on the JWT regardless of which scopes were approved, enable Always include all user authorization info on the token on the Inbound App. See Scope Token Settings. That setting is separate from scope↔role mapping on the Resource. For an MCP Server Resource, the same setting lives on the MCP server, or on its dynamic registration template if it uses one.

Note

If a scope requires a role the user does not have, they cannot grant consent for that scope. Only users with matching RBAC roles see and approve those permissions during the consent flow.

Example: user-delegated CRM access

ScopeMapped Descope roleWhat it allows
contacts.readSales RepList and view contacts
contacts.writeSales ManagerCreate and update contacts
  1. A partner Inbound App requests contacts.write.
  2. The user must hold Sales Manager (the role linked to that scope) to consent to it.
  3. On success, the token will include the granted scope: "contacts.write" and the mapped roles: ["Sales Manager"].
  4. Your API can authorize using roles / permissions under Sales Manager, or require contacts.write in scope—or both.

Machine (M2M) and autonomous clients

Client credentials, JWT bearer, and autonomous Agentic Clients have no interactive user consent. There is no end-user role check at consent time.

StepWhat happens
1. RequestThe client authenticates as itself (client_credentials, JWT bearer, etc.) and requests scopes for a Resource.
2. PolicyPolicies decide which scopes this client may receive (often matched with client.tags or client identity).
3. TokenThe access token includes the policy-granted scopes and the roles mapped to those scopes on the API Resource.

Use this when many M2M clients share tags and Policies grant each tag a specific Resource + scope set. Backends that already authorize from Descope roles and permissions can read roles on the M2M token the same way they do for user tokens, without mapping every OAuth scope in application code.

Example:

  1. API Resource scope claims.read is mapped to role Claims Reader (with permissions your APIs already check).
  2. A Policy allows clients with tag smithrx-batch to receive claims.read on that Resource.
  3. A client_credentials token for such a client includes scope: "claims.read" and roles: ["Claims Reader"].

Note

M2M clients do not "hold" user RBAC roles for consent. The roles in the token come from the Resource scope ↔ role mapping for the scopes Policies (and client configuration) grant—not from assigning roles to the client as if it were a user.

User-information scopes

Scopes that share user information with a client, such as profile and email, aren't defined on a Resource. They're attribute scopes, defined once for the project and added to each Inbound App or Federated OIDC App, where they map to the claims that appear in tokens and the /userinfo response.

Enforce on your API

Validate the JWT, then enforce aud, scope, and—if you authorize via RBAC—roles / permissions. See Enforce scopes and Resource claims.

ApproachWhen to use
Require scopeStandard OAuth resource-server pattern; fine-grained per route
Require roles / permissionsSame RBAC model as first-party apps; permissions live under roles that scopes map to
BothScope for least-privilege at the OAuth boundary; roles for existing permission checks

MCP Server Resources

MCP Server Resources define tool-level OAuth scopes for an MCP server. Instead of mapping Resource scopes to RBAC roles, you can map Resource scopes to Connection scopes for when a tool needs credentials from the Connections vault.

FieldDescription
Scope nameMachine-friendly string your MCP server enforces (e.g. mcp:schedule_meetings)
Connection scopesOAuth or API permissions on linked Connections to fetch at tool runtime
Consent descriptionText shown on the user consent screen
Allow user to decline scopeWhether the user can uncheck the scope on the consent screen. Off by default, so the scope must be accepted.

When a client is granted mcp:hubspot, your server can fetch the matching Connection token for HubSpot without storing third-party secrets in the MCP server itself.

Defined MCP scopes appear in the server's discovery document under scopes_supported.

RBAC and MCP Server Resources

Role-based checks for MCP flows use Agentic Identity Hub policies (for example user.roles CONTAINS "scheduler") and consent-flow logic, not scope-to-role fields on the MCP Server Resource definition. API Resources use scope ↔ RBAC on the Resource; MCP Server Resources use scope ↔ Connection mapping on the Resource.

For more configuration details, see MCP server scopes.

Was this helpful?

On this page