---
schema_version: "1"
id: 36d64ec89a35c09ef65f1f35aba6b42cdaa0669d539eea40a29b2f990e7f2696
title: "Headless Identity APIs: Headless Guest Flow for Private Clients"
collection: admin
version: current
locale: en-us
portal_url: https://docs.salesforce.com/admin/current/en-us/xcloud/264-0-0/remoteaccess_headless_guest_private_client.md
canonical_url: https://help.salesforce.com/s/articleView?id=xcloud.remoteaccess_headless_guest_private_client.htm&release=264.0.0&type=5
source_site: help.salesforce.com
content_type: documentation
content_hash: bec7be9930bde6cd3d8f421be2319e23ff98c7b8ea5c7460796b71915d11e11d
description: For users who interact with your off-platform app but aren’t necessarily logged in, you can use the Headless Guest Flow to identify users with a unique visitor ID (UVID). When the user logs in or registers, you can carry the UVID forward and maintain any contextual information associated with it, like a user’s preferences. This flow is a variation of the Authorization Code and Credentials Flow.
products:
  - Security
  - Cross Cloud
release: "264"
---
# Headless Identity APIs: Headless Guest Flow for Private Clients

For users who interact with your off-platform app but aren’t necessarily logged in, you can use the Headless Guest Flow to identify users with a unique visitor ID (UVID). When the user logs in or registers, you can carry the UVID forward and maintain any contextual information associated with it, like a user’s preferences. This flow is a variation of the Authorization Code and Credentials Flow.

### 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 (not available in all orgs) and Lightning Experience</td></tr><tr class=""><td class="slds-cell-wrap" style="vertical-align:top;">Available in: <strong>Enterprise</strong>, <strong>Unlimited</strong>, and <strong>Developer</strong> Editions</td></tr></tbody></table>

Before setting up this flow, complete these steps.

- [Complete Prerequisites for Headless Identity](https://help.salesforce.com/s/articleView?id=xcloud.headless_identity_prerequisites.htm&release=264.0.0&type=5 "Before you get started with a Headless Identity implementation for your off-platform apps, cross off these prerequisites in Salesforce.")
- Integrate your off-platform app with Salesforce using one of these options. Make sure that you configure additional policies for the guest flow.
    - [Configure an External Client App for the Authorization Code and Credentials Flow](https://help.salesforce.com/s/articleView?id=xcloud.eca_authorization_code_credentials.htm&type=5&language=en_US)
    - [Configure a Connected App for the Authorization Code and Credentials Flow](https://help.salesforce.com/s/articleView?id=xcloud.authorization_code_credentials_configure.htm&release=264.0.0&type=5 "The Authorization Code and Credentials Flow is the foundation of headless login, registration, passwordless login, and guest user identity. Before setting up these features, enable the Authorization Code and Credentials Flow at an org-wide level and configure required settings and access policies for your connected app.")

For example, you host an ecommerce app outside of the Salesforce platform. You want users to be able to save items to a cart without logging in. You can use the guest user flow to generate a UVID for the user, and you can store the user’s cart information and tie it to the UVID. When the user eventually logs in or registers, you pass the UVID into a headless login or registration flow. Because you have the cart context from the UVID, you can save the user’s items, giving them a better experience.

The shopping cart example is just one of many possibilities when it comes to the UVID and guest flow. Other possibilities include understanding what makes your users want to sign up for your app and remembering their preferences.

The guest flow and UVID are supported only for JSON Web Token (JWT)-based access tokens. To connect the UVID to a named user, you must configure the named user flow to issue JWT-based access tokens too.

These instructions tell you how to implement the flow for a private client with its own backend. Private clients have a secure place to store your app’s consumer secret, which functions as a password for the code exchange, so we recommend sending the consumer secret when you request an access token.

We also recommend that you further protect your flow by implementing the OAuth 2.0 Proof Key for Code Exchange (PKCE) extension. PKCE helps ensure that the client that initiates the flow is the same client that completes it. For more information about how PKCE works and how you can enforce it, see [Proof Key for Code Exchange (PKCE) Extension](https://help.salesforce.com/s/articleView?id=xcloud.remoteaccess_pkce.htm&release=264.0.0&type=5 "To improve the security of your OAuth and authentication provider implementations, use the OAuth 2.0 Proof Key for Code Exchange (PKCE) extension. You can require PKCE at an org-wide level, require it for a specific connected app, and automatically enable it for supported authentication providers.").

Here’s an overview of the guest flow. These steps cover the flow up to the point when the guest user is identified, but not logged in.

![Sequence diagram showing the headless guest user flow for private clients](https://sf-zdocs-cdn-prod.zoominsoftware.com/tdta-xcloud-identity-264-0-0-production-enus/699dab6f-8f1a-4662-b24f-6521d5b747f7/identity/images/headless_guest_private_clients.png)

- The unknown visitor arrives at the app, or performs an action like clicking a button (1).
- The app looks for a UVID. If it can’t find one, it requests a UVID from its client backend (2).
- If requested, the client backend generates a UVID and sends it to your app (3).
- Your app receives the UVID (4a).
- If you’re using PKCE, your app generates PKCE parameters (4b).
- To get an authorization code, your app sends the UVID in a headless GET or POST request to the authorization endpoint (`services/oauth2/authorize`) (5).
- Salesforce validates the UVID and returns a 302 redirect to a preconfigured URL containing the authorization code (6).
- Your app’s client backend extracts the code and other parameters from the 302 redirect and exchanges the code for an access token with a request to the Salesforce token endpoint (`services/oauth2/token`) (7).
- Salesforce returns a guest JWT-based access token with the UVID in the subject claim (8).
- Your app’s client backend processes the guest JWT-based access token and stores the UVID value, which it can keep private. It returns a guest session, and optionally, the guest token (9).
- Your app receives the token response and creates the guest session (10).
- The previously unknown visitor now has a guest session tied to the UVID value in the access token (11).

As mentioned in step 7 for a private client, your build a server-side callback handler that can extract the 302 redirect and return an authorization code to your app. To see how you can build this handler, see [Authorization Code and Credentials Flow for Private Clients](https://help.salesforce.com/s/articleView?id=xcloud.remoteaccess_authorization_code_credentials_flow.htm&type=5&language=en_US), which includes an example Apex handler exposed as a REST resource.

## Unknown End User Arrives at Your App

The flow starts when an end user visits your app. You can also configure it to start when the user performs an action, such as saving an item to a cart.

## App Requests a UVID If Necessary

Your app tries to find a UVID from previous visits to the app. For example, it determines if it can pull the UVID from a cookie or from local storage in the browser. If the app can’t find a UVID, it requests one from its client backend.

## Client Backend Generates a UVID

If requested, the client backend generates a UVID value. Salesforce isn’t involved in generating, storing, or maintaining the UVID. It’s entirely up to your app. The only requirement is that the UVID must be a Version 4 universally unique identifier (v4 UUID).

## App Receives UVID

Your app receives the UVID from the client backend.

## App Generates PKCE Parameters

If you’re using PKCE, your app generates `code_verifier` and `code_challenge` parameters.

The PKCE specification defined in [RFC 7636](https://datatracker.ietf.org/doc/html/rfc7636) also includes an optional `code_challenge_method` parameter that you can send in the authorization request. Salesforce ignores any value that you send in this parameter and defaults to `SHA256`.

## App Exchanges the UVID for an Authorization Code

Your app headlessly sends a GET or POST request to the Salesforce authorization endpoint on your Experience Cloud site. The request contains the UVID and other parameters to identify the app and specify the type of request.

You have two options for how you send the UVID in this request. You can either send a plain UVID value, or send a JWT-based access token with the UVID minted into it. For example, if you have a JWT-based access token from a previous session, sending the token to the authorization endpoint is an easy way to reuse it without specifically parsing it for the UVID.

Include these headers in your request.

<table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small " summary="Authorization Request: Headers">
        <caption>Authorization Request: Headers</caption>
        <colgroup>
          <col style="width:33.33333333333333%">
          <col style="width:33.33333333333333%">
          <col style="width:33.33333333333333%">
        </colgroup>
        <thead class="slds-text-title_caps ">
          <tr class="">
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d35768e270">Header</th>
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d35768e273">Required?</th>
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d35768e276">Description</th>
          </tr>
        </thead>
        <tbody>
          <tr class="">
            <td data-label="Header" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e270 ">
              <code>Uvid-Hint</code>
            </td>

            <td data-label="Required?" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e273 ">Required if you don’t send the UVID in the request body. You must always
              include a UVID—whether it’s sent in the header or in the request body.</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e276 ">
              <p>Contains either the UVID as a plain value or a JWT-based access token with a
                UVID minted into it.</p>
              <p>If you send the UVID as a plain value, include a <code>UVID</code> prefix before the value so that the request is
                formatted as <code>Uvid-Hint: UVID &lt;UVID
                  value&gt;</code>.</p>
              <p style="margin-bottom:0;">If you send a JWT-based access token with a UVID, include a
                <code>JWT</code> prefix before the value, such as
                <code>Uvid-Hint: JWT &lt;access token containing
                    UVID&gt;</code>.
              </p>
            </td>

          </tr>
          <tr class="">
            <td data-label="Header" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e270 ">
              <code>Auth-Request-Type</code>
            </td>

            <td data-label="Required?" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e273 ">Yes.</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e276 ">Specifies the type of request you want to make to Salesforce. For headless
              passwordless login, this value must be set to <code>guest</code>.</td>

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

Include these parameters in the request body.

<table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small " summary="Authorization Request: Body Parameters">
        <caption>Authorization Request: Body Parameters</caption>
        <colgroup>
          <col style="width:33.33333333333333%">
          <col style="width:33.33333333333333%">
          <col style="width:33.33333333333333%">
        </colgroup>
        <thead class="slds-text-title_caps ">
          <tr class="">
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d35768e356">Parameter</th>
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d35768e359">Required?</th>
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d35768e362">Description</th>
          </tr>
        </thead>
        <tbody>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e356 ">
              <code>uvid_hint</code>
            </td>

            <td data-label="Required?" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e359 ">Required if you don’t include the UVID in the header.</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e362 ">
              <p>Contains either the UVID as a plain value or a JWT-based access token with a
                UVID minted into it.</p>
              <p>If you send the UVID as a plain value, include a <code>UVID</code> prefix before the value so that the request is
                formatted as <code>uvid_hint=UVID &lt;UVID
                  value&gt;</code>.</p>
              <p style="margin-bottom:0;">If you send a JWT-based access token with a UVID, include a
                <code>JWT</code> prefix before the value, such as
                <code>uvid_hint=JWT &lt;access token containing
                    UVID&gt;</code>.
              </p>
            </td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e356 ">
              <code>client_id</code>
            </td>

            <td data-label="Required?" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e359 ">Yes.</td>

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

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e356 ">
              <code>response_type</code>
            </td>

            <td data-label="Required?" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e359 ">Yes.</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e362 ">The OAuth 2.0 grant type that your app requests. Because this flow is a
              variation of the Authorization Code and Credentials Flow, this value must be <code>code_credentials</code>.</td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e356 ">
              <code>redirect_uri</code>
            </td>

            <td data-label="Required?" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e359 ">Yes.</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e362 ">
              <p>The URL where users are redirected after successful authentication. The <code>redirect_uri</code> must match one of the values in the
                external client app or connected app Callback URL field. Otherwise, the approval
                fails. This value must be URL encoded.</p>
              <p style="margin-bottom:0;">For private clients, use a <code>redirect_uri</code> that points to your server-side
                callback handler.</p>
            </td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e356 ">
              <code>code_challenge</code>
            </td>

            <td data-label="Required?" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e359 ">Only if you’re using PKCE, which we always recommend, especially for a public
              client.</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e362 ">
              <p>Specifies the SHA256 hash value of the <code>code_verifier</code> value in the token request. Set this parameter to help
                prevent authorization code interception attacks. The value must be Base-64 URL
                encoded as defined in <a href="https://tools.ietf.org/html/rfc4648#section-5" target="_blank">https://tools.ietf.org/html/rfc4648#section-5</a></p>
              <p>If a <code>code_challenge</code> is provided in the authorization
                request and a <code>code_verifier</code> is provided in
                the token request, Salesforce compares the two values. If the <code>code_challenge</code> is invalid or doesn’t match, the
                login fails with the <code>invalid_request</code> error
                code.</p>
              <p style="margin-bottom:0;">If the <code>code_challenge</code> is provided
                in the authorization request, but there’s no <code>code_verifier</code> in the token request, the login fails with the <code>invalid_grant</code> error code.</p>
            </td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e356 ">
              <code>scope</code>
            </td>

            <td data-label="Required?" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e359 ">Yes.</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e362 ">
              <p>Permissions that define the type of protected resources the app can access. The
                values that you send in this request must match or be a subset of the scopes
                assigned to your external client app or connected app.</p>
              <p style="margin-bottom:0;">For more information about
                each scope and its purpose, see <a href="https://help.salesforce.com/s/articleView?id=xcloud.remoteaccess_oauth_tokens_scopes.htm&amp;type=5&amp;language=en_US" target="_blank">OAuth Tokens and Scopes</a>.</p>
            </td>

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

These example authorization requests all implement PKCE.

Here’s an example request where the UVID is passed as a plain value in the request header.

```
POST /services/oauth2/authorize? HTTP 1.1
Host: MyExperienceCloudSite.my.site.com
Uvid-Hint: UVID abcd-1234-efgh
Auth-Request-Type: guest

response_type=code_credentials&
client_id=***********&
redirect_uri=https://www.MyExperienceCloudSite.my.site.com/services/oauth2/echo&
code_challenge=********&
scope=openid
```

Here’s an example request where the UVID is passed in a JWT-based access token in the header.

```
POST /services/oauth2/authorize? HTTP 1.1
Host: MyExperienceCloudSite.my.site.com
Uvid-Hint: JWT **************
Auth-Request-Type: guest

response_type=code_credentials&
client_id=***********&
redirect_uri=https://www.MyDomainName.my.site.com/services/apexrest/code/exchange&
code_challenge=********
scope=openid
```

In this example, the UVID is passed as a plain value in the request body.

```
POST /services/oauth2/authorize? HTTP 1.1
Host: MyExperienceCloudSite.my.site.com
Auth-Request-Type: guest

uvid_hint=UVID abcd-1234-efgh&
response_type=code_credentials&
client_id=***********&
redirect_uri=https://www.MyDomainName.my.site.com/services/apexrest/code/exchange&
code_challenge=********
scope=openid
```

## Salesforce Returns a 302 Redirect

Salesforce validates the UVID. If the UVID was passed as a plain value, Salesforce validates its format. If it was passed as a JWT-based access token, Salesforce checks the validity of the token.

Salesforce then returns an HTTP 302 redirect to a preconfigured URL containing the authorization code. If the flow is happening in the browser, the 302 redirect is processed in the browser and Salesforce automatically sends the redirect response to the redirect URL, which points to the server-side callback handler on the client backend. Here’s an example preconfigured URL.

```
https://www.MyDomainName.my.site.com/services/apexrest/code/exchange?code=aPrxC1*******
&sfdc_community_url=https%3A%2F%2FMyDomainName.my.site.com&sfdc_community_id=0DBxxxxxxxxxxxx
```

## Client Backend Extracts the Code and Exchanges It for an Access Token

The client backend extracts the authorization code and other parameters from the preconfigured URL. It then initiates a code exchange by sending the code and other parameters in a headless POST request to the `/services/oauth2/token` endpoint.

Include these headers in the request.

<table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small " summary="Code Exchange: Header">
        <caption>Code Exchange: Header</caption>
        <colgroup>
          <col style="width:33.33333333333333%">
          <col style="width:33.33333333333333%">
          <col style="width:33.33333333333333%">
        </colgroup>
        <thead class="slds-text-title_caps ">
          <tr class="">
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d35768e594">Parameter</th>
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d35768e597">Required?</th>
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d35768e600">Description</th>
          </tr>
        </thead>
        <tbody>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e594 ">
              <code>Uvid-Hint</code>
            </td>

            <td data-label="Required?" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e597 ">Yes.</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e600 ">
              <p>Contains either the UVID as a plain value or a JWT-based access token with a
                UVID minted into it.</p>
              <p style="margin-bottom:0;">For the code exchange, don’t include a prefix for the UVID.
                For example, if you pass the UVID as a plain value, the header is just <code>Uvid-Hint: abcd-1234-efgh</code>. If you pass in a
                JWT-based access token, it’s <code>Uvid-Hint: &lt;access
                    token containing UVID&gt;</code>.</p>
            </td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e594 ">
              <code>Auth-Request-Type</code>
            </td>

            <td data-label="Required?" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e597 ">Yes.</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e600 ">Specifies the type of request you want to make to Salesforce. For headless
              passwordless login, this value must be set to <code>guest</code>.</td>

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

Include these parameters in the request body.

<table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small " summary="Code Exchange: Body Parameters">
        <caption>Code Exchange: Body Parameters</caption>
        <colgroup>
          <col style="width:33.33333333333333%">
          <col style="width:33.33333333333333%">
          <col style="width:33.33333333333333%">
        </colgroup>
        <thead class="slds-text-title_caps ">
          <tr class="">
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d35768e672">Parameter</th>
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d35768e675">Required?</th>
            <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d35768e678">Description</th>
          </tr>
        </thead>
        <tbody>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e672 ">
              <code>code</code>
            </td>

            <td data-label="Required?" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e675 ">Yes.</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e678 ">The authorization server creates an authorization code, which is a short-lived
              token, and passes it to the client after successful authentication. The client sends
              the authorization code to the authorization server to obtain an access token and,
              optionally, a refresh token.</td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e672 ">
              <code>client_id</code>
            </td>

            <td data-label="Required?" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e675 ">Yes.</td>

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

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e672 ">
              <code>client_secret</code>
            </td>

            <td data-label="Required?" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e675 ">Yes.</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e678 ">The consumer secret of the external client app or connected app.</td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e672 ">
              <code>redirect_uri</code>
            </td>

            <td data-label="Required?" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e675 ">Yes.</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e678 ">
              <p>The URL where users are redirected after a successful authentication. The
                redirect URI must match one of the values in the external client app or connected
                app Callback URL field. Otherwise, the approval fails. This value must be URL
                encoded.</p>
              <p style="margin-bottom:0;">For private clients, use a <code>redirect_uri</code> that points to your server-side callback
                handler.</p>
            </td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e672 ">
              <code>grant_type</code>
            </td>

            <td data-label="Required?" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e675 ">Yes.</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e678 ">The type of validation that the app can provide to prove it’s a safe visitor.
              Because this flow is a variation of the Authorization Code and Credentials Flow, the
              value must be <code>authorization_code</code>.</td>

          </tr>
          <tr class="">
            <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e672 ">
              <code>code_verifier</code>
            </td>

            <td data-label="Required?" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e675 ">Only if you’re using PKCE.</td>

            <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d35768e678 ">
              <p>Specifies 128 bytes of random data with high entropy to make guessing the code
                value difficult. Set this parameter to help prevent authorization code interception
                attacks. The value must be base64url-encoded as defined in <a href="https://datatracker.ietf.org/doc/html/rfc4648#section-5" target="_blank">https://datatracker.ietf.org/doc/html/rfc4648#section-5</a>.</p>
              <p>If there’s a <code>code_verifier</code> value in the token request and a
                <code>code_challenge</code> value in the authorization
                request, Salesforce compares the two values. If the <code>code_verifier</code> is invalid or doesn’t match, the login fails with the
                <code>invalid_grant</code> error code.
              </p>
              <p style="margin-bottom:0;">If the
                <code>code_verifier</code> value is in the token
                request, but there’s no <code>code_challenge</code> value
                in the authorization request, the login fails with the <code>invalid_grant</code> error code.
              </p>
            </td>

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

Here’s an example token request that implements PKCE. In this example, the UVID is sent as a plain value.

```
POST services/oauth2/token? HTTP 1.1
Host: MyExperienceCloudSite.my.site.com
Auth-Request-Type: guest
Uvid_Hint: abcd-1234-efgh

code=********&
client_id=**********&
client_secret=*********&
redirect_uri=https://www.MyDomainName.my.site.com/services/apexrest/code/exchange&
grant_type=authorization_code&
code_verifier=*******
```

## Salesforce Grants a JWT-Based Access Token

After validating the app’s credentials. Salesforce returns a guest JWT-based access token and a state to the client backend. The guest access token contains the UVID in the subject (`sub`) claim. Here’s an example snippet of a JWT-based access token. As a reminder, these tokens have three components: a header, payload, and signature. This example shows you the payload. As you can see, the UVID value in the `sub` claim is prefixed with `uvid`.

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

{
  "scp": "open_id",
  "aud": [
    "https://example.com"
  ],
  "sub": "uvid:abcd-1234-efgh",
  "nbf": "1675197036",
  "iss": "https://MyExperienceCloudSite.my.site.com",
  "exp": "1675198836",
  "iat": "1675197036",
   jti”: xRb**********”
  "client_id": "**********"
}
```

For a full explanation of each claim in a JWT-based access token, see [JWT-Based Access Tokens](https://help.salesforce.com/s/articleView?id=xcloud.jwt_access_tokens.htm&type=5&language=en_US) in Salesforce Help.

## Client Backend Processes Access Token Response

The client back-end processes the access token response and stores the UVID value. It returns a guest session to your app. It can also return the JWT-based access token, but it isn’t required.

## App Creates the Guest Session

Your app receives the token response from its client back end and creates a guest session.

## Unknown User Is Now Identified

The unknown end user now has a guest session tied to the UVID value returned in the JWT-based access token. At this point, it’s up to you what you want to do with the UVID. To learn how to pass it into a named user authorization flow, see [Extending the Guest User Flow into a Named User Flow](https://help.salesforce.com/s/articleView?id=xcloud.remoteaccess_headless_guest_extension.htm&release=264.0.0&type=5 "When you complete a headless guest flow in your off-platform app, you get a guest JWT-based access token with the user’s unique visitor ID (UVID) minted into it. To bring the UVID and all of its associated context into a named user session, you can pass the UVID into a new authorization flow, like a headless login or registration flow.").