## Documentation Index

Fetch the complete documentation index at: [/docs/llms.txt](/content/docs/llms.txt)

Use this file to discover all available pages before exploring further.

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:

```
    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](/content/docs/api-reference/b2b/api/connected-apps/tokens/connected-app-access-token-object/index.html) 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](/content/docs/api-reference/b2b/api/connected-apps/tokens/connected-app-id-token-object/index.html), for [Consumer](/content/docs/api-reference/consumer/api/connected-apps/tokens/connected-app-id-token-object/index.html)) is granted to the Connected App and what claims are present in the ID Token and in the `UserInfo` API response (for [B2B](/content/docs/api-reference/b2b/api/connected-apps/methods/get-userinfo/index.html), for [Consumer](/content/docs/api-reference/consumer/api/connected-apps/methods/get-userinfo/index.html)).

| 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**](/content/docs/connected-apps/oauth-learn-more/client-types/index.html) OAuth clients can request the `full_access` scope to enable access to the Exchange Access Token endpoint (for [B2B](/content/docs/api-reference/b2b/api/sessions/exchange-access-token/index.html), for [Consumer](/content/docs/api-reference/consumer/api/sessions/exchange-access-token/index.html)).

| 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](/content/docs/multi-tenant-auth/enterprise-ready/rbac/create-rbac-policy/index.html), for [Consumer](/content/docs/consumer-auth/authorization/create-rbac-policy/index.html)). Create custom scopes to support the different use-cases.

### Defining Custom Scopes

Your application’s RBAC policy is managed in the [Stytch RBAC dashboard](/content/dashboard/rbac/index.html). Before defining custom scopes, you must define **Resources** (for [B2B](/content/docs/multi-tenant-auth/enterprise-ready/rbac/create-rbac-policy/index.html), for [Consumer](/content/docs/consumer-auth/authorization/create-rbac-policy/index.html)) 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:

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

You could define the corresponding scopes:

```
    [
      { '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.

```
    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](/content/docs/api-reference/b2b/api/connected-apps/methods/authenticate-access-token-local/index.html) method:

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

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