> ## Documentation Index
> Fetch the complete documentation index at: https://stytch.com/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# OAuth scopes

> Understanding OAuth Scopes in Stytch Connected Apps

During an OAuth flow, a Connected App requests authorization from a user via the `scope` parameter - a space-delimited list of capabilities that Connected App wishes to be granted. Clients should request access tokens with the minimal set of capabilities required for that client to function.

For example, a client may need "read" access to a user's resources, but doesn't need to update resources. This client should request only read-only access, and obtain an access token that cannot be used to update resources.

A Connected App Client can request a token with the scope of openid profile read:data as shown:

```javascript theme={null}
const scopes = ['openid', 'profile', 'read:data']
const params = new URLSearchParams({
  client_id: 'connected-app-test-d731954d-dab3-4a2b-bdee-07f3ad1be888',
  redirect_uri: 'https://app.example/oauth/callback',
  response_type: 'code',
  scope: scopes.join(' '), // space-delimited string
  state: 'some-state-value',
});

// Pass these params to the Authorization URL page in your application 
window.location.href = `https://idp.example/oauth2/authorize?${params.toString()}`;
```

[Access Tokens](/api-reference/b2b/api/connected-apps/tokens/connected-app-access-token-object) granted to Stytch Connected Apps will contain a `scope` field representing the capabilities granted to the token.

***

## **Built-in Scopes**

Built-in scopes are preconfigured scopes within the Stytch platform.

### **Built-in OIDC Scopes**

The Stytch platform supports all scopes defined by the [OpenID Connect Core](https://openid.net/specs/openid-connect-core-1_0.html#ScopeClaims) specification with no prior configuration required.

These scopes control whether an ID Token (for [B2B](/api-reference/b2b/api/connected-apps/tokens/connected-app-id-token-object), for [Consumer](/api-reference/consumer/api/connected-apps/tokens/connected-app-id-token-object)) is granted to the Connected App, and what claims are present in the ID Token and in the `UserInfo` API response (for [B2B](/api-reference/b2b/api/connected-apps/methods/get-userinfo), for [Consumer](/api-reference/consumer/api/connected-apps/methods/get-userinfo)).

| Name      | Effect when granted                                                                                                       |
| :-------- | :------------------------------------------------------------------------------------------------------------------------ |
| `openid`  | An OIDC `id_token` will be returned from the `/oauth2/token` endpoint                                                     |
| `email`   | The `email` and `email_verified` claims will be returned in the `id_token`                                                |
| `phone`   | The `phone_number` and `phone_number_verified` claims will be returned in the `id_token`                                  |
| `profile` | The `name`, `given_name`, `middle_name`, `family_name`, `picture`, and `locale` claims will be returned in the `id_token` |

The Stytch platform also supports scopes defined for [Offline Access](https://openid.net/specs/openid-connect-core-1_0.html#OfflineAccess) of user data.

| Name             | Effect when granted                                                                                            |
| :--------------- | :------------------------------------------------------------------------------------------------------------- |
| `offline_access` | A `refresh_token` will be returned from the `/oauth2/token` endpoint for use in subsequent refresh token flows |

### **Built-in Stytch Platform Scopes**

The Stytch platform supports additional scopes used for specific actions in the Stytch API. [**First Party**](/connected-apps/oauth-learn-more/client-types) OAuth clients can request the `full_access` scope to enable access to the Exchange Access Token endpoint (for [B2B](/api-reference/b2b/api/sessions/exchange-access-token), for [Consumer](/api-reference/consumer/api/sessions/exchange-access-token)).

| Name          | Effect when granted                        |
| :------------ | :----------------------------------------- |
| `full_access` | Enables the Exchange Access Token API call |

## **Custom Scopes**

Your application can additionally define custom scopes tied to your **RBAC (Role-Based Access Control)** system (for [B2B](/multi-tenant-auth/enterprise-ready/rbac/create-rbac-policy), for [Consumer](/consumer-auth/authorization/create-rbac-policy)). Create custom scopes to support the different use-cases

### Defining Custom Scopes

Your application's RBAC policy is managed in the [Stytch RBAC dashboard](https://stytch.com/dashboard/rbac). Before defining custom scopes, you must define **Resources** (for [B2B](/multi-tenant-auth/enterprise-ready/rbac/create-rbac-policy), for [Consumer](/consumer-auth/authorization/create-rbac-policy)) for those scopes to act on. Each resource has a set of actions that can be performed upon that resource. Scopes are then composed of **permissions**, where each permission is an `action` applied to a `resource`.

For example, given the resources of:

```json theme={null}
[
  {
    'resource': 'images',
    'actions': ['read', 'write', 'delete']
  },
  {
    'resource': 'documents',
    'actions': ['read', 'write', 'comment', 'delete']
  }
];
```

You could define the corresponding scopes:

```json expandable theme={null}
[
  {
    'scope': 'read:data',
    'description': 'Read access to company data',
    'permissions': [
      { 'resource': 'documents', 'actions': ['read'] },
      { 'resource': 'images', 'actions': ['read'] }
    ]
  },
  {
    'scope': 'write:data',
    'description': 'Write access to company data',
    'permissions': [
      { 'resource': 'documents', 'actions': ['write'] },
      { 'resource': 'images', 'actions': ['write'] }
    ]
  },
  {
    'scope': 'data:*',
    'description': 'Full access to company data',
    'permissions': [
      { 'resource': 'documents', 'actions': ['*'] },
      { 'resource': 'images', 'actions': ['*'] }
    ]
  }
];
```

Stytch supports flexible naming conventions for scopes (e.g., `readonly:content`, `read:*`, and `content:readonly` are all allowed).

### What custom scopes can be granted?

The end user authorizing the application can only grant scopes that correspond to **permissions they themselves possess**:

* Permissions can be spread across **multiple roles**.
* Grantable scopes are determined by checking if the union of the user's roles covers all required permissions.

**Example:**

* Scope `write:data` requires `write` permission on both `documents` and `images`
* End User Roles:
  * `document_manager` ➔ grants `write` on `documents`
  * `image_uploader` ➔ grants `write` on `images`

✅ Scope is **grantable** because combined roles satisfy all requirements.

**Unmet permissions** will result in the scope being filtered out during the OAuth consent flow.

### Consent screen customization

By default, the consent screen will show the `description` of each scope being requested. The consent screen can be tailored using the `getIDPConsentManifest` SDK callback. Use this callback to group scopes by logical domain, provide additional documentation, or otherwise customize the language displayed to the end user.

```javascript expandable theme={null}
const isProfileScope = (scope) => scope === 'openid' || scope === 'email' || scope === 'profile';
const isDataScope = (scope) => !isProfileScope(scope);

const getScopeDescription = (scope) => {
  // ...
};

const getManifest = ({ scopes, clientName }) => [
  {
    header: `${clientName} wants to view your Profile`,
    items: [
      {
        text: 'View information stored in your Profile about your user.',
        details: scopes.filter(isProfileScope).map(getScopeDescription),
      },
    ],
  },
  {
    header: `${clientName} wants to access your Data`,
    items: scopes.filter(isDataScope).map(getScopeDescription),
  },
];
```

This allows branding-friendly and understandable displays of scope groupings to end users.

### Access Token Scope Validation

Many Access Token JWT libraries will check for a particular scope within the token before letting the call proceed. While this approach is satisfactory for many applications, applications with complex RBAC requirements should check for the *underlying permission* that the scope grants instead. Authorizing at the permission level instead of the scope level creates a level of abstraction that makes it easier to introduce new scopes, or change the permissions attached to a scope over time.

For example, both the `write:data` and the `data:*` scope grant permission to write to a document. Checking for the underlying permission makes it easier to add new scopes (e.g. `documents:*`) in the future without requiring application code changes.

Use the Stytch SDK [Authenticate Access Token](/api-reference/b2b/api/connected-apps/methods/authenticate-access-token-local) method:

```typescript theme={null}
stytch.idp.introspectTokenLocal({
  access_token: 'eyJ...',
  authorization_check: {
    resource: 'documents',
    action: 'write'
  }
});
```

If the token lacks the required permission, this call will fail.
