Custom JWT Claims
Custom claims allow you to embed additional data directly in the JWT access token issued by Auris. Instead of making a separate API call to fetch user data after authentication, your backend can read the claim directly from the verified token.
Custom claims are configured per application in the Console and resolved at token issuance time.
When to Use Custom Claims
Custom claims are useful when:
- Your backend needs user metadata (department, plan, tenant ID) on every request without an extra lookup
- A third-party API expects specific claims in the JWT (e.g., a payment gateway expecting a
subscription_tierclaim) - You want to encode permission or role information into the token for stateless authorization
- Different applications in your tenant need different user data in their tokens
Claims in access tokens are readable by anyone who holds the token. Do not embed sensitive data (passwords, secrets, financial data) in JWT claims. Claims are also included in the token size — large payloads increase the size of every HTTP Authorization header.
Claim Types
Auris supports four claim value types:
STATIC
A fixed string, number, or boolean value — the same for every user who receives a token from this application.
{ "environment": "production" }
{ "app_version": "2.1.0" }
{ "feature_flag_x": true }Use when: You need to identify which application issued the token, or embed configuration values that do not change per user.
USER_ATTRIBUTE
A value drawn from the authenticated user’s profile. The available attributes are:
| Attribute Key | Description |
|---|---|
email | User’s primary email address |
firstName | User’s first name |
lastName | User’s last name |
username | User’s username (Keycloak username) |
phoneNumber | User’s verified phone number |
metadata | The entire user metadata JSON object |
metadata.{key} | A specific key from the user metadata JSON |
{ "user_email": "[email protected]" }
{ "department": "engineering" } // via metadata.department
{ "phone": "+15551234567" }Use when: Your backend or downstream service needs user identity data available in the token without additional API calls.
ROLE_BASED
A different value returned depending on which roles the user holds. The first matching role wins. A fallback value is returned if no role matches.
// Configuration:
{
"plan": {
"Administrator": "enterprise",
"Pro User": "pro",
"default": "free"
}
}
// Resulting claim for a Pro User: { "plan": "pro" }
// Resulting claim for an Administrator: { "plan": "enterprise" }
// Resulting claim for a user with no matching role: { "plan": "free" }Use when: Different roles in your system correspond to feature tiers, access levels, or pricing plans that downstream services need to act on.
EXPRESSION
A computed value using a simple expression evaluated against the user context. Expressions have access to user, roles, and metadata variables.
// Expressions are JavaScript-like (evaluated in a sandboxed context)
user.email.split('@')[1] // => "acme.com" (email domain)
roles.includes('Administrator') // => true | false
metadata.orgId ?? 'default' // => orgId from metadata or "default"
user.firstName + ' ' + user.lastName // => "Alice Smith"Expressions are evaluated in a sandboxed context. They have no access to require, import, process, eval, network calls, or file system operations.
Use when: You need a derived or computed value that is not directly available as a user attribute.
Reserved Claims
The following claim keys are reserved by Auris and the OAuth2/OIDC specification. They cannot be overridden by custom claims:
| Reserved Claim | Description |
|---|---|
iss | Token issuer (your Auris domain) |
sub | Subject — the user’s ID |
aud | Audience — your client ID |
exp | Expiry timestamp |
iat | Issued-at timestamp |
jti | JWT ID (unique token identifier) |
type | Token type (user or m2m) |
scope | Granted OAuth scopes |
roles | Array of the user’s role names |
email | User’s email (from standard OIDC claims) |
name | User’s display name |
Attempting to create a custom claim with a reserved key returns a validation error.
Console Setup
Open Custom Claims configuration
In the Auris Console, navigate to Applications → select your application → Custom Claims tab.
Add a claim
Click Add Claim and configure:
- Claim Key: The JSON key in the token (e.g.,
department,plan,tenant_id) - Claim Type: STATIC, USER_ATTRIBUTE, ROLE_BASED, or EXPRESSION
- Value: Type-specific value configuration
Preview the claim
Use the Preview button to resolve the claim for a specific user before saving. This calls the preview API endpoint with the user’s actual data.
Activate the claim
Toggle Active on the claim. Deactivated claims are skipped during token issuance (useful for testing without deleting the configuration).
Examples
Example 1: Embedding User Department
Requirement: Your backend needs to know the user’s department on every request.
Setup:
- Claim Key:
department - Type:
USER_ATTRIBUTE - Attribute:
metadata.department
Resulting token:
{
"sub": "user-id-123",
"email": "[email protected]",
"roles": ["Employee"],
"department": "Engineering",
...standard claims...
}Backend usage:
// No additional API call needed — department is in the token
const { department } = verifyToken(req.headers.authorization.slice(7))
console.log(department) // "Engineering"Example 2: Subscription Plan Badge
Requirement: A third-party analytics tool expects a subscription_plan claim indicating the user’s tier.
Setup:
- Claim Key:
subscription_plan - Type:
ROLE_BASED - Mapping:
Enterprise Customer→enterprisePro Customer→proFree Tier→free- Default →
free
Resulting token for an Enterprise Customer:
{
"sub": "user-id-456",
"roles": ["Enterprise Customer", "Invoice Viewer"],
"subscription_plan": "enterprise",
...
}Example 3: Email Domain Extraction
Requirement: A multi-tenant backend routes requests based on the user’s email domain (company).
Setup:
- Claim Key:
email_domain - Type:
EXPRESSION - Expression:
user.email.split('@')[1]
Resulting token:
{
"sub": "user-id-789",
"email": "[email protected]",
"email_domain": "contoso.com",
...
}Example 4: Static Application Environment
Requirement: Distinguish tokens from production vs. staging application registrations.
Setup (on the production app):
- Claim Key:
env - Type:
STATIC - Value:
production
Setup (on the staging app):
- Claim Key:
env - Type:
STATIC - Value:
staging
API Endpoints
/api/applications/:id/custom-claimsRequires: view:applicationsList all custom claims configured for an application, including their type, value configuration, and active status.
/api/applications/:id/custom-claimsRequires: manage:applicationsCreate a new custom claim. Body: { claimKey: string, valueType: 'STATIC' | 'USER_ATTRIBUTE' | 'ROLE_BASED' | 'EXPRESSION', staticValue?: string, userAttribute?: string, roleMapping?: Record<string, string>, expression?: string, isActive?: boolean }.
/api/applications/:id/custom-claims/:claimIdRequires: manage:applicationsUpdate a custom claim’s configuration or active status.
/api/applications/:id/custom-claims/:claimIdRequires: manage:applicationsDelete a custom claim. Tokens issued after deletion will not contain the claim. Tokens issued before deletion remain unchanged until they expire.
/api/applications/:id/custom-claims/previewRequires: view:applicationsPreview claim resolution for a specific user. Body: { userId: string }. Returns the resolved claim values as they would appear in a token for that user.
Token Size Considerations
Each custom claim adds to the size of every JWT access token issued by the application. JWT tokens are sent as HTTP headers on every authenticated request. Keep claims concise:
| Consideration | Guidance |
|---|---|
| String values | Keep under 100 characters per claim |
| Avoid full metadata objects | Use metadata.{key} to extract specific fields, not the entire metadata object |
| Number of claims | Aim for fewer than 10 custom claims per application |
| Role-based claim values | Use short identifiers (pro, free) not full descriptions |
Oversized tokens can cause 431 Request Header Fields Too Large errors on some proxies and load balancers (typically with headers over 8KB).
Related Guides
- Roles & Permissions (RBAC) — Role configuration referenced by ROLE_BASED claims
- Fine-Grained Authorization — Object-level authorization using FGA
- M2M Client Credentials — Custom claims also apply to M2M tokens