Token Claims Management
Token management in Descope includes controlling the claim payloads in JWTs that are issued to users and machines.
In practice, this usually means configuring custom claims beyond standard claims like sub, iss, and exp so downstream services can make authorization and personalization decisions without extra backend calls.
For step-by-step setup details, see the Custom Claims flow action and JWT Templates pages.
Where Claims Appear in Tokens
When configured, custom claims can appear in every JWT Descope issues for the user or access key, including:
- Session tokens — short-lived JWTs sent to your application on every request.
- Refresh tokens — used to issue new session tokens. Custom claims travel with them, so they count against cookie size limits.
- ID tokens — issued when Descope is acting as an OIDC provider.
- Access Key JWTs — issued when an M2M Access Key is exchanged for a session.
Two Ways to Configure Claims
Note
You can manage JWT Templates as code with our infrastructure as code (IaC) providers, such as Terraform.
There are two places you can configure claims in Descope:
| Method | Scope | When to use |
|---|---|---|
| JWT Template (preferred) | Project-wide, code-manageable | Claims that should appear on every JWT issued by a project, application, or Inbound App. Best for consistent token claims. |
| Custom Claims flow action | Per-flow | Claims that depend on flow context — conditional logic, connector responses, step-up authentication, or values collected from the user during the flow. |
It's worth noting that you can use both together. If a claim is set in both places, the Custom Claims flow action wins and overrides the JWT Template value for that flow.
Supported Claim Value Types
Custom claim values can be:
- Strings, booleans, or numbers — simple, flat values.
- Dynamic values — pulled from Descope user attributes, tenant attributes, or other available context. These automatically refresh when the underlying value changes (see Dynamic Claims below).
- JSON objects — for grouping related fields under a single claim key (see Nested JSON Claims below).
Both the JWT Template editor and the Custom Claims flow action support a simple mode for flat key/value entry and an advanced mode for defining the claim payload as a JSON object.
Nested JSON Claims
Note
This is useful when downstream consumers expect related data grouped under a single key (for example, gateways like Hasura or external authorization systems that read structured claim objects).
You can use a JSON object as the value of a custom claim.

In advanced mode with JWT Templates, you can set the claim key to a JSON object instead of a flat value:
{
"my_json_custom_claim": {
"hello": "I am a custom claim",
"that_has": "Nested Json"
}
}The object is embedded directly into the issued JWT under the specified key:
{
"amr": ["oauth"],
"drn": "DS",
"exp": 1776282239,
"iat": 1776281639,
"iss": "P32jk5Nq29jcuXmAz56iGq5uRb7m",
"my_json_custom_claim": {
"hello": "I am a custom claim",
"that_has": "Nested Json"
},
"sub": "U3B57mYzHbJY8HFvjHvhRkTPq5xr"
}You can nest objects multiple levels deep, mix object and scalar values within the same template, and combine static fields with dynamic user-attribute references inside the same nested structure.
Dynamic Claim Updates
Claim values backed by a Descope user or tenant attribute update automatically whenever the underlying attribute changes and the user's session is refreshed. You don't need to re-issue tokens manually.
This is useful for:
- Real-time access control — role or permission changes take effect on the next refresh.
- Reflecting up-to-date profile data (display name, locale, preferences) without an extra API call.
- Multi-tenant context —
tenant_id,tenant.name, or tenant-specific attributes that shift when a user switches tenants.
Dynamic values can be used inside both flat and nested claim definitions.
Claim Limits
Each key can have a maximum of 60 characters, each claim value can have a maximum of 500 characters, and each JWT can have a maximum of 100 keys.
These limits apply across both the JWT Template and the Custom Claims flow action. Because Descope stores custom claims in the refresh token (typically held in a cookie), large or numerous claims also contribute to your overall cookie size — see JWT Claims security best practices for guidance.
Security Considerations
Custom claims are read by every service that consumes the JWT. A few things to keep in mind:
- Don't store sensitive data: JWTs are Base64-encoded, not encrypted. Treat anything in a claim as visible to anyone who holds the token.
- Trust only server-set claims: Claims added by a client SDK are placed under an
nsecclaim and should not be trusted by your backend. Claims set via JWT Templates or the Custom Claims flow action (server-side) are trusted. - Override standard claims carefully: You can override claims like
audoramr, but doing so has implications for token validation and audit trails.
For full guidance, see JWT Claims security best practices.