---
schema_version: "1"
id: 5cd94eb4df58579c3dcd5c0c8e0a6ac0583cbdf6e44fd35cbfed47a238e1de68
title: JWT-Based Access Tokens
collection: admin
version: current
locale: en-us
portal_url: https://docs.salesforce.com/admin/current/en-us/xcloud/264-0-0/jwt_access_tokens.md
canonical_url: https://help.salesforce.com/s/articleView?id=xcloud.jwt_access_tokens.htm&release=264.0.0&type=5
source_site: help.salesforce.com
content_type: documentation
content_hash: f554c0758bd1dddbd94aa39335e70c7db63fb42b7a4b409e8303b2d38b6df288
description: "Salesforce supports two types of access tokens: opaque tokens and JSON Web Tokens (JWT)-based access tokens. An opaque access token is formatted as a string that you can’t decode unless you call the Salesforce User Info endpoint. A JWT-based access token is formatted as a JSON object that contains all of the information required to authorize an app. This transparent format makes JWT-based access tokens easier to use for services built outside of the Salesforce platform. You can easily parse and validate JWT-based access tokens locally on your off-platform service, without calling a Salesforce endpoint. By locally introspecting tokens, you can improve the performance and efficiency of your authorization flows."
products:
  - Security
  - Cross Cloud
release: "264"
---
# JWT-Based Access Tokens

Salesforce supports two types of access tokens: opaque tokens and JSON Web Tokens (JWT)-based access tokens. An opaque access token is formatted as a string that you can’t decode unless you call the Salesforce User Info endpoint. A JWT-based access token is formatted as a JSON object that contains all of the information required to authorize an app. This transparent format makes JWT-based access tokens easier to use for services built outside of the Salesforce platform. You can easily parse and validate JWT-based access tokens locally on your off-platform service, without calling a Salesforce endpoint. By locally introspecting tokens, you can improve the performance and efficiency of your authorization flows.

### Required Editions

<table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small edition"><colgroup><col></colgroup><tbody><tr class=""><td class="slds-cell-wrap" style="vertical-align:top;">Available in: both Salesforce Classic and Lightning Experience</td></tr><tr class=""><td class="slds-cell-wrap" style="vertical-align:top;">Available in: <strong>All</strong> Editions</td></tr></tbody></table>

Compared to opaque access tokens, JWT-based access tokens have different functionality and limitations. For example, JWT-based access tokens can be used only to access REST APIs. To see how the token types compare, visit [Access Tokens](https://help.salesforce.com/s/articleView?id=xcloud.remoteaccess_access_tokens.htm&release=264.0.0&type=5 "Access tokens are your key to Salesforce APIs. When a client successfully completes an authorization flow, whether it’s a standard OAuth 2.0 flow or a headless identity flow, Salesforce issues an access token that can be used to access protected Salesforce data. Salesforce supports two types of access tokens: opaque tokens and JSON Web Token (JWT)-based access tokens. Each type has its own merits and limitations based on your use case.") in Salesforce Help.

You can issue JWT-based access tokens for all [authorization flows](https://help.salesforce.com/s/articleView?id=xcloud.remoteaccess_oauth_flows.htm&language=en_US).

## Token Format

JWT-based access tokens use the JWT structure, with a header, a payload, and a signature. The header has information about the token, such as its token type. The payload contains a set of claims with information about the token, the user, and the app. The signature portion contains the token’s cryptographic signature. This signature consists of the Base64-encoded header and payload and a secret, signed using the algorithm specified in the `alg` claim.

Here’s a detailed overview of the header and payload.

![Note](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-xcloud-identity-264-0-0-production-enus/699dab6f-8f1a-4662-b24f-6521d5b747f7/images/icon_note.png)

Note Depending on how the tokens are issued, they can contain additional claims that aren’t listed here.

JWT Header Claims  
| Header Claim | Description |
| --- | --- |
| `alg` (algorithm) | The algorithm that’s used to sign the JWT-based access token, allowing you to verify that it hasn’t changed since it was issued. Salesforce supports only the RS256 algorithm, so the value of this claim must be `RS256`. |
| `typ` (type) | The type of content stored in the token. This claim helps apps distinguish the token from other types of data. For JWT-based access tokens, this value is `JWT`. |
| `kid` (key ID) | A string that’s registered with Salesforce indicating that a key was used to sign the token, which helps to prove its authenticity. |
| `tty` (token type) | The type of token. The value is set to `sfdc-core-token`. |
| `tnk` (tenant key) | The tenant key identifying the Salesforce org that issued the JWT-based access token. This value is defined so that Salesforce can find and verify the correct public keys for that org. |
| `ver` (version) | The version of the JWT library. |

Here’s an example header.

```
{
  "tnk": "example/00XXXXXX",
  "ver": "1.0",
  "kid": "CORE_ATJWT************",
  "tty": "sfdc-core-token",
  "typ": "JWT",
  "alg": "RS256"
}
```

The payload always includes these claims.

<table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small " summary="JWT Payload Required Claims">
        <caption>JWT Payload Required Claims</caption>
        <colgroup>
          <col style="width:50%">
          <col style="width:50%">
        </colgroup>
        <thead class="slds-text-title_caps ">
          <tr class="">
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d72555e212">Payload Claim</th>
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d72555e215">Description</th>
          </tr>
        </thead>
        <tbody>
          <tr class="">
            <td data-label="Payload Claim" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e212 "><code>aud</code> (audience)</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e215 ">The intended audience of the JWT access token as determined by its use case.
              The <code>aud</code> claim is formatted as a JSON array of
              strings.</td>

          </tr>
          <tr class="">
            <td data-label="Payload Claim" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e212 "><code>exp</code> (expiration time)</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e215 ">The expiration time of the JWT access token. The token can’t be accepted on or
              after this time. The expiration time must be after the current date and
              time.</td>

          </tr>
          <tr class="">
            <td data-label="Payload Claim" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e212 "><code>iss</code>(issuer)</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e215 ">The My Domain login URL or the URL of the Experience Cloud site that’s issuing
              the JWT access token. For example,
              <samp class="filepath">MyDomainName.my.site.com</samp>.
            </td>

          </tr>
          <tr class="">
            <td data-label="Payload Claim" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e212 ">
              <code>mty</code>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e215 ">For internal use only.</td>

          </tr>
          <tr class="">
            <td data-label="Payload Claim" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e212 "><code>nbf</code> (not before time)</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e215 ">The client must receive the JWT after the date and time expressed in the
              <code>nbf</code> claim. If the JWT is sent before this
              date and time, the client can’t accept it.
            </td>

          </tr>
          <tr class="">
            <td data-label="Payload Claim" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e212 ">
              <code>sfi</code>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e215 ">Internal identifier reserved for future use.</td>

          </tr>
          <tr class="">
            <td data-label="Payload Claim" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e212 "><code>sub</code> (subject)</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e215 ">
              <p>Identifies the user that is the subject of the JWT access token. The <code>sub</code> value is prefixed with the type of user
                identifier. Salesforce supports these prefixes.</p>
              <ul>
                <li><code>uid</code>—Indicates a business-to-business
                  (B2B) user. The prefix is followed by the user’s 15-character user ID. For
                  example, <code>uid:005x00000000001</code>.</li>
                <li><code>b2c</code>—Indicates a business-to-consumer
                  (B2C) user. The prefix is followed by the user’s 15-character user ID. For
                  example, <code>b2c:005x00000000001</code>.</li>
                <li><code>uvid</code>—Indicates that the claim is storing
                  a unique visitor ID (UVID). The UVID is a Version 4 universally unique
                  identifier (v4 UUID), such as <code>abcd-1234-efgh</code>, that you can generate during a headless guest flow.
                  The guest flow issues JWT-based access tokens with a UVID in the <code>sub</code> claim. If you pass the token or UVID into a
                  named user flow, the new JWT-based access token puts the UVID in the <code>obo</code> claim instead, and the <code>sub</code> claim stores the user ID.</li>
                <li><code>app</code>—For internal use only.</li>
              </ul>
            </td>

          </tr>
          <tr class="">
            <td data-label="Payload Claim" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e212 "><code>scp</code> (scopes)</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e215 ">A list of Salesforce supported scopes, including custom scopes, formatted as a
              JSON array of scope names. The scopes are separated by spaces. The token can include
              any Salesforce scopes except for the <code>full</code> scope.</td>

          </tr>
        </tbody>
      </table>

The payload can also include these optional claims.

<table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small " summary="JWT Payload Optional Claims">
        <caption>JWT Payload Optional Claims</caption>
        <colgroup>
          <col style="width:50%">
          <col style="width:50%">
        </colgroup>
        <thead class="slds-text-title_caps ">
          <tr class="">
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d72555e384">Payload Claim</th>
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d72555e387">Description</th>
          </tr>
        </thead>
        <tbody>
          <tr class="">
            <td data-label="Payload Claim" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e384 ">
              <code>acx</code>
            </td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e387 ">For internal use only.</td>

          </tr>
          <tr class="">
            <td data-label="Payload Claim" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e384 "><code>client_id</code> (consumer key)</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e387 ">The consumer key of the Salesforce external client app or connected app that
              issued the token.</td>

          </tr>
          <tr class="">
            <td data-label="Payload Claim" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e384 "><code>iat</code> (issued at)</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e387 ">The time when the JWT was issued. You can use the value of this claim to figure
              out how old the JWT is.</td>

          </tr>
          <tr class="">
            <td data-label="Payload Claim" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e384 "><code>roles</code>(role list)</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e387 ">
              <p>Defines properties for the token that services can use to control access, such
                as permission sets and roles. Salesforce fully controls the values in this claim.
                The claim doesn’t include a comprehensive list of a user’s access privileges. For
                example, a permission set that’s assigned to the user sometimes doesn’t show up in
                this list. </p>
              <p>The values in this claim are formatted as an array of prefixed
                strings. Salesforce supports these prefixes.</p>
              <ul>
                <li><code>ps</code>—Indicates a permission set, expressed
                  as a 15-character ID. For example, <code>ps:000x00000000001</code>.</li>
                <li><code>role</code>—Indicates a role defined in
                  Salesforce. For example, <code>role:Commerce
                      Admin</code>.</li>
                <li><code>other</code>–Contains a free-form string that
                  can indicate any other factor that affects access to the token. For example, it
                  can contain information about the type of user, such as <code>other:System Administrator</code>.</li>
              </ul>
              <p style="margin-bottom:0;">Sometimes, this claim is an empty array.</p>
            </td>

          </tr>
          <tr class="">
            <td data-label="Payload Claim" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e384 "><code>obo</code> (on behalf of)</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d72555e387 ">Whoever has the token can complete actions on behalf of the value in this
              claim. For Salesforce, this claim is used to link a UVID to a named user when you
              pass a guest token into a named user flow. The guest token contains the UVID in the
              <code>sub</code> claim. After completing a named user
              flow, the new access token puts the UVID in the <code>obo</code> claim and stores the user ID in the <code>sub</code> claim.
            </td>

          </tr>
        </tbody>
      </table>

Here’s an example payload. Because this example has a UVID in the `obo` claim, you can assume that this token was issued after passing a UVID into a named user flow.

```
{
  "scp": "api",
  "aud": [
    "https://example.com"
  ],
  "sub": "uid:005x00000000001",
  "nbf": "1675197036",
  "iss": "https://example.com",  "exp": "1675198836",
  "iat": "1675197036",
  “obo”: “uvid:abcd-1234-efgh”,
  "client_id": "***********",
  “mty”: “oauth”,
  “sfi”: “********”
}
```