---
title: "Five Reasons Why Your Auth0 Permissions Are Not in your Access Token"
description: "Decoding your Auth0 JWT and seeing an empty permissions array? Here are 5 common reasons your Auth0 RBAC permissions are missing and how to fix them fast."
authors:
  - name: "Carla Urrea Stabile"
    url: "https://auth0.com/blog/authors/carla-stabile/"
date: "Sep 3, 2026"
category: "Developers,Tips"
tags: ["jwt", "access token", "rbac"]
url: "https://auth0.com/blog/five-reasons-permissions-not-in-access-token/"
---

# Five Reasons Why Your Auth0 Permissions Are Not in your Access Token

You set up RBAC, created a permission, assigned it to a role, assigned the role to a user, and requested a token. When you decode it, the `permissions` array is empty or missing entirely, and you do not understand why.

There are five reasons this happens. They all produce the same symptom and they are all silent, which is why this is one of the most common questions I have seen out there. This post covers all five, in the order you should check them, so let's get into it. 

## Reason 1: You Are Not Passing an audience Parameter

I wish I could tell this has not happened to me but it has, so many times. Without an `audience` parameter in the authorization request, Auth0 issues an [opaque token](https://auth0.com/docs/secure/tokens/access-tokens#opaque-access-tokens). Opaque tokens have no claims at all, so you will not see `permissions`, `sub`, or anything else decodable. If you paste the token into [jwt.io](https://jwt.io) and it says the token is invalid, this is likely why.

![jwt.io Opaque Access Token](https://images.ctfassets.net/23aumh6u8s0i/2JP9K8c5HCuInOLjvkLCSt/719b07d0f0e5bdbee4aa663e4fc0b5e3/jwt-opaque.png)

The fix is to add an `audience` to your authorization request, set to the API Identifier from your Auth0 API settings. It is case-sensitive and has to match exactly.

```bash
# Without audience — Auth0 issues an opaque token
GET /authorize
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=https://your-app.com/callback
  &scope=openid profile email

# With audience — Auth0 issues a JWT with claims
GET /authorize
  ?response_type=code
  &client_id=YOUR_CLIENT_ID
  &redirect_uri=https://your-app.com/callback
  &scope=openid profile email
  &audience=https://your-api.example.com
```

The `audience` value comes from **Applications > APIs > your API > General Settings > Identifier**. If there is a trailing slash in the dashboard, include it in your request

![Access Token with Claims](https://images.ctfassets.net/23aumh6u8s0i/1VDxSsbSzy1Cee7vfSNdwz/b321668486a53de0dc9ae0676b1aea93/jwt.png)

## Reason 2: The "Add Permissions in the Access Token" Toggle Is Off

[RBAC has two separate settings on the API](https://auth0.com/docs/get-started/apis/enable-role-based-access-control-for-apis), and both need to be on. The first enables RBAC. The second, "Add Permissions in the Access Token," is what actually puts those permissions into the token. You can have RBAC enabled and still get a token with no permissions if the second toggle is off.

To check: **Auth0 Dashboard > Applications > APIs > your API > Settings > RBAC Settings**. You will see two checkboxes. Both need to be checked.

![RBAC Settings](https://images.ctfassets.net/23aumh6u8s0i/7HPdAWy5Ou060mdblyJ8f7/bb6a685f95ee96e11e9a6a6e48295db2/rbacsettings.png)

Make sure that you are checking the same API whose identifier you supplied as `audience` in your app. RBAC settings and permissions are configured per API.

## Reason 3: The Permission Is on the Role, but the Role Is not on the User

Auth0's permission model has two steps: you assign permissions to roles, and you assign roles to users. If you did the first step but not the second, the token will have no permissions. It is a straightforward miss, but it comes up consistently in community threads.

To check: **Auth0 Dashboard > User Management > Users > find the user > Roles tab**. The role should appear there. If it does n'ot, assign it.

![User with roles assigned](https://images.ctfassets.net/23aumh6u8s0i/5LNFn6Bv9Yerxz917WXJtH/6bc5d07dbf9f219773493f8a1af08386/users.png)

If you are using Auth0 Organizations, there is an additional layer to understand. Tenant roles and organization roles are separate concepts in Auth0, not the same role at different scopes. A tenant role named `admin` and an organization role named `admin` are two distinct objects, and assigning one does not assign the other.
Which roles end up in the token also depends on how the user logged in. When the user logs in the context of an organization, Auth0 issues a token with the roles assigned to that user within that specific org. If no `organization` parameter is present, Auth0 issues a token with the user's tenant-level roles instead.

So if your users are logging in via an organization (with `organization=org_abc` in the `/authorize` request) but the role is only assigned at the tenant level, they will get an access token with no permissions even though everything looks correctly configured from the tenant side. The fix is to [assign the role to the user at the organization level](https://auth0.com/docs/manage-users/organizations/configure-organizations/add-member-roles), not just at the tenant level.

To check org membership roles: **Auth0 Dashboard > Organizations > your org > Members > find the user > Roles**.

## Reason 4: You Are Decoding the ID Token Instead of the Access Token

Permissions live in the access token, not the [ID token](https://auth0.com/docs/secure/tokens/id-tokens). The ID token is for your application to verify the user's identity. The access token is what your API checks to determine what that user is allowed to do. If you are decoding the wrong one, you will not see permissions even when everything else is configured correctly.

To confirm you are looking at the right token, decode it and check the `aud` claim. An ID token is normally addressed to your application Client ID. An access token for your API should list that API identifier as its audience. Depending on the token format, `aud` may be a string or an array. The token sent in `Authorization: Bearer <token>` to your API should be the access token.

> [Learn more about the difference between Access Tokens and ID Tokens](https://auth0.com/blog/id-token-access-token-what-is-the-difference/)

## Reason 5: You Are Using the Client Credentials Flow

The `permissions` array is a RBAC feature for user-based flows. The Client Credentials grant issues an access token representing an application, not an end user. Because there is no user involved, roles assigned to users do not affect this token.
For M2M authorization, authorize the application for your API and grant it the scopes it needs. The resulting token commonly expresses those grants in its scope claim.

To authorize what an M2M application can do, you grant it scopes directly on the API rather than through roles.

To set this up: **Auth0 Dashboard > Applications > your M2M app > APIs tab > Authorize** the API and select the scopes it should be allowed to request. When the application calls `/oauth/token` with those scopes, the token will include `"scope": "read:data write:data"` rather than a `permissions` array.

If your API currently checks for `permissions`, you will need to handle both claims, you could look into the `gty` claim, and verify if it says `client-credentials`. 
Bonus: Your Custom Claim Is Colliding with a Reserved Claim

This one applies if you are adding permissions through a Post-Login Action rather than using Auth0's built-in RBAC permissions claim. 

Do not try to create your own permissions claim. Auth0 uses that claim for built-in RBAC permissions, so treating it as an application-defined custom claim can conflict with Auth0-managed token behavior.

Prefer an application-specific, namespaced claim (See [Auth0 docs on custom claims](https://auth0.com/docs/secure/tokens/json-web-tokens/create-custom-claims) for the full collision rules.) such as https://your-app.example/permissions. Namespaced claims reduce the chance of collisions with standard or Auth0-reserved claims.

```javascript
exports.onExecutePostLogin = async (event, api) => {
  // Avoid using Auth0's RBAC claim name for app-defined data.
  api.accessToken.setCustomClaim('permissions', ['read:reports']);

  // Use Namespaced URI for app-specific data instead.
  api.accessToken.setCustomClaim('https://your-app.com/permissions', ['read:reports']);
};
```

## Quick Diagnostic Checklist

Work through these in order and you will find it.

1. Are you passing `audience` in the authorization request?
2. Is RBAC enabled on the API? Is "Add Permissions in the Access Token" also on?
3. Is the role assigned to the user, not just the permission assigned to the role?
4. Are you decoding the access token, not the ID token?
5. Are you using the client credentials flow? Check the `scope` claim, not `permissions`.

For the full reference, see the [Auth0 docs on enabling RBAC for APIs](https://auth0.com/docs/get-started/apis/enable-role-based-access-control-for-apis).