JWT claims are data — use them
A JWT isn’t just an authentication token. It’s a signed payload carrying structured data about the caller: their identity (sub), their roles or permissions (permissions, roles), their tenant (tenant_id, org_id), their email, their token expiry. This data is verified when RequestRocket validates the token signature — but most teams don’t take the next step of actually using those claims to enforce access policy.
This post covers how to extract JWT claims at the RequestRocket gateway and use them in authorization rules (to allow or deny requests) and filters (to redact fields from responses based on the caller’s claims) — specifically with RequestRocket’s jwtVerify credential type.
Setting up JWT verification
First, create a jwtVerify proxy credential. This tells RequestRocket to validate the Authorization: Bearer <token> header on inbound requests against your identity provider’s JWKS endpoint:
POST /clients/{clientId}/credentials
{
"credentialType": "proxy",
"credentialAuthType": "jwtVerify",
"credentialName": "app-jwt-verify",
"credentialRegion": "us-east-1",
"credentialSecret": {
"jwksUri": "https://your-auth-provider.com/.well-known/jwks.json",
"audience": "https://api.myapp.com",
"issuer": "https://your-auth-provider.com/"
}
}Any proxy using this credential will reject requests with missing, invalid, or expired JWTs before the request is forwarded.
Enforcing JWT claims with authorization rules
Authorization rules are evaluated pre-request — before anything is forwarded to the upstream. Rules support a token array that matches against decoded JWT claim values using regex patterns. This is the correct mechanism for blocking or allowing requests based on what’s in the token.
Require a specific permission scope
POST /clients/{clientId}/proxies/{proxyId}/rules
{
"effect": "deny",
"methods": ["POST", "PUT", "DELETE"],
"path": {
"path": { "pattern": "^/v1/projects" },
"presence": "must_exist"
},
"token": [
{
"claim": { "pattern": "^permissions$" },
"value": { "pattern": "projects:write" },
"presence": "must_absent"
}
],
"notes": "Deny mutating project operations — projects:write permission missing"
}presence: "must_absent" means: this rule fires when the projects:write permission is not in the token. The request is rejected with a 403.
Require a subscription tier
POST /clients/{clientId}/proxies/{proxyId}/rules
{
"effect": "deny",
"methods": ["GET"],
"path": {
"path": { "pattern": "^/v1/analytics/advanced" },
"presence": "must_exist"
},
"token": [
{
"claim": { "pattern": "^plan$" },
"value": { "pattern": "^(pro|enterprise)$" },
"presence": "must_absent"
}
],
"notes": "Feature gate: advanced analytics requires pro or enterprise plan"
}Require multiple claims (AND semantics)
All token checks within a single rule must match for the rule to fire. Use this to combine several requirements:
POST /clients/{clientId}/proxies/{proxyId}/rules
{
"effect": "deny",
"methods": ["DELETE"],
"path": {
"path": { "pattern": "^/v1/users/" },
"presence": "must_exist"
},
"token": [
{
"claim": { "pattern": "^roles$" },
"value": { "pattern": "admin" },
"presence": "must_absent"
}
],
"notes": "Deny user deletion — admin role required"
}Extracting claims into variables for path matching
The variables system in rules lets you extract a claim value and bind it to a named variable for use in path patterns. This enables tenant isolation — ensuring a caller can only reach resources that belong to their own tenant:
POST /clients/{clientId}/proxies/{proxyId}/rules
{
"effect": "allow",
"methods": ["GET", "POST", "PUT", "DELETE"],
"variables": [
{
"name": "orgId",
"source": "jwtClaim",
"key": "org_id"
}
],
"path": {
"path": {
"pattern": "^/v1/organisations/{{orgId}}(/.*)?$"
},
"presence": "must_exist"
},
"notes": "Tenant isolation: callers may only access their own organisation's resources"
}At evaluation time, {{orgId}} is replaced with the actual org_id value from the validated JWT. With proxyDefaultRuleEffect: "deny", a request to /v1/organisations/org-abc/projects from a token with org_id: "org-xyz" fails the path check and is denied.
Using token checks in filters for response-level redaction
While rules control whether a request proceeds, filters control what comes back in the response. Filters also support token criteria — but here they determine which responses to apply redaction to, not whether to block the request.
For example, redact the internal costBasis field from order responses for callers who don’t have the finance role:
POST /clients/{clientId}/proxies/{proxyId}/filters
{
"methods": ["GET"],
"token": [
{
"claim": { "pattern": "^roles$" },
"value": { "pattern": "finance" },
"presence": "must_absent"
}
],
"operations": [
{
"effect": "destroy",
"jsonPath": { "pattern": "\\.costBasis$" },
"notes": "Remove costBasis from responses for non-finance callers"
}
],
"notes": "Response redaction: costBasis visible to finance role only"
}This filter fires on responses to callers whose token does not contain the finance role, removing the costBasis field from the JSON payload before it’s returned. The request itself proceeds normally — only the response is modified.
Important: token checks are only evaluated for jwtVerify credentials
The token criteria in both rules and filters — and the jwtClaim variable source — are only evaluated when the proxy’s proxy credential is credentialAuthType: "jwtVerify". On proxies using other credential types (key, bearer, basic, etc.), token checks are skipped.
Ensure your claim-dependent rules and filters are applied to proxies configured with jwtVerify credentials.
What this gives you at the gateway
Every JWT claim check enforced at the gateway is one less check your backend needs to perform. The backend receives only requests that have already passed the claim requirements, and responses have already had role-restricted fields removed. For multi-tenant APIs, this means tenant isolation is a hard gateway constraint — not just a backend convention.
Next steps
JWT claim extraction and matching is available on any proxy with a jwtVerify credential. Read the RequestRocket documentation for the full rule and filter schemas, or start for free.