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
| Available in: both Salesforce Classic and Lightning Experience |
| Available in: All Editions |
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 in Salesforce Help.
You can issue JWT-based access tokens for all authorization flows.
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.
| 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.
| Payload Claim | Description |
|---|---|
aud (audience) |
The intended audience of the JWT access token as determined by its use case.
The aud claim is formatted as a JSON array of
strings. |
exp (expiration time) |
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. |
iss(issuer) |
The My Domain login URL or the URL of the Experience Cloud site that’s issuing the JWT access token. For example, MyDomainName.my.site.com. |
mty
|
For internal use only. |
nbf (not before time) |
The client must receive the JWT after the date and time expressed in the
nbf claim. If the JWT is sent before this
date and time, the client can’t accept it. |
sfi
|
Internal identifier reserved for future use. |
sub (subject) |
Identifies the user that is the subject of the JWT access token. The
|
scp (scopes) |
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 full scope. |
The payload can also include these optional claims.
| Payload Claim | Description |
|---|---|
acx
|
For internal use only. |
client_id (consumer key) |
The consumer key of the Salesforce external client app or connected app that issued the token. |
iat (issued at) |
The time when the JWT was issued. You can use the value of this claim to figure out how old the JWT is. |
roles(role list) |
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. The values in this claim are formatted as an array of prefixed strings. Salesforce supports these prefixes.
Sometimes, this claim is an empty array. |
obo (on behalf of) |
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
sub claim. After completing a named user
flow, the new access token puts the UVID in the obo claim and stores the user ID in the sub claim. |
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”: “********”
}

