---
schema_version: "1"
id: d019c8cbee4601d1f1afbdc2591a136f302ef112058c7254afabf93fcde2c3fc
title: "OAuth 2.0 for First-Party Applications: Generate a Client Attestation JWT"
collection: admin
version: current
locale: en-us
portal_url: https://docs.salesforce.com/admin/current/en-us/xcloud/264-0-0/remoteaccess_auth_challenge_generate_jwt.md
canonical_url: https://help.salesforce.com/s/articleView?id=xcloud.remoteaccess_auth_challenge_generate_jwt.htm&release=264.0.0&type=5
source_site: help.salesforce.com
content_type: documentation
content_hash: c0b9880c030c807bbcfab7de2eaa89147665b2b05e5b73166c49298e18276629
description: When using headless identity flows that implement the OAuth 2.0 for First-Party Applications draft standard, use a client attestation JWT to prove that apps sending requests to Salesforce are first-party apps created by your company.
products:
  - Security
  - Cross Cloud
release: "264"
---
# OAuth 2.0 for First-Party Applications: Generate a Client Attestation JWT

When using headless identity flows that implement the OAuth 2.0 for First-Party Applications draft standard, use a client attestation JWT to prove that apps sending requests to Salesforce are first-party apps created by your company.

### 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>Enterprise</strong>, <strong>Unlimited</strong>, and <strong>Developer</strong> Editions</td></tr></tbody></table>

Salesforce requires that a JWT is signed using RSA SHA256, which uses an uploaded certificate as the signing secret. Before you get started, complete these prerequisites.

- Upload an X509 Certificate to a Java Key Store (JKS). The certificate size can't exceed 4 KB. If it does, try using a DER-encoded file to reduce the size.
- Register the certificate with your external client app using the `clientAssertionCertificate` field in the ExtlClntAppOauthSettings type.
- Build an app that generates a JWT, which is signed with the X509 Certificate’s private key. The associated external client app uses the certificate to verify the signature. The JWT must conform with the general format rules specified in [https://tools.ietf.org/html/rfc7519](https://tools.ietf.org/html/rfc7519).
    
    ![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 Salesforce doesn’t require JWT ID (JTI) claims in your JWT bearer tokens. However, if you pass a JTI claim in your JWT bearer token, Salesforce validates that the JTI claim hasn’t been sent before. This validation prevents JWT replay attacks.

To create a valid JWT, take these steps.

1. Construct a JWT header with this format: `{"alg":"RS256"}`.
2. Base64-URL encode the JWT header as defined in [http://tools.ietf.org/html/rfc4648#page-7](http://tools.ietf.org/html/rfc4648#page-7). The result is similar to `eyJhbGciOiJSUzI1NiJ9`.
3. Construct a JSON Claims Set for the JWT with these parameters.
    
    <table class="slds-table slds-table_bordered slds-max-medium-table_stacked slds-m-bottom_small ">
            <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="d36563e89">Parameter</th>
                <th scope="col" class="slds-cell-wrap" style="vertical-align:top;" id="d36563e91">Description</th>
              </tr>
            </thead>
            <tbody>
              <tr class="">
                <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d36563e89 "><code>iss</code></td>
                <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d36563e91 ">The issuer must contain the OAuth <code>client_id</code> for
                  the external client app for which you registered the certificate.</td>
              </tr>
              <tr class="">
                <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d36563e89 "><code>aud</code></td>
                <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d36563e91 ">
                  <p>The audience identifies the authorization server as an intended audience. The
                    authorization server must verify that it’s an intended audience for the token. </p>
                  <p style="margin-bottom:0;">Use your
                    Experience Cloud site URL, such as
                    <samp class="filepath">https://MyExperienceCloudSite.my.site.com</samp>.
                  </p>
                </td>
              </tr>
              <tr class="">
                <td data-label="Parameter" class="slds-cell-wrap" style="vertical-align:top;" headers="d36563e89 "><code>exp</code></td>
                <td data-label="Description" class="slds-cell-wrap" style="vertical-align:top;" headers="d36563e91 ">The date and time at which the token expires, expressed as the number of seconds
                  from 1970-01-01T0:0:0Z measured in UTC. Salesforce allows a 3-minute buffer for clock
                  skew. For example, if the expiration time is set to 1735743600 seconds or January 1, 2025
                  at 15:00:00 UTC, the token is still valid until 15:03:00 UTC on this date.</td>
              </tr>
            </tbody>
          </table>
    
    Here's an example JWT claims set.
    
    ```
    {"iss": "3MVG99OxTyEMCQ3gNp2PjkqeZKxnmAiG1xV4oHh9AKL_rSK.BoSVPGZHQ
    ukXnVjzRgSuQqGn75NL7yfkQcyy7", 
    "aud": "https://MyExperienceCloudSite.my.site.com", 
    "exp": "1333685628"}
    ```
4. Base64url encode the JWT Claims Set without any line breaks. Here's an example.
    
    ```
    eyJpc3MiOiAiM01WRzk5T3hUeUVNQ1EzZ05wMlBqa3FlWkt4bm1BaUcxeFY0b0hoOUFLTF9yU0su
    Qm9TVlBHWkhRdWtYblZqelJnU3VRcUduNzVOTDd5ZmtRY3l5NyIsICJwcm4iOiAibXlAZW1haWwu
    Y29tIiwgImF1ZCI6ICJodHRwczovL2xvZ2luLnNhbGVzZm9yY2UuY29tIiwgImV4cCI6ICIxMzMz
    Njg1NjI4In0=
    ```
5. Create a string for the encoded JWT Header and the encoded JWT Claims Set in this format.
    
    ```
    encoded_JWT_Header + "." + encoded_JWT_Claims_Set
    ```
    
    In this example, the encoded JWT Header is highlighted.
    
    ```
    eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiAiM01WRzk5T3hUeUVNQ1EzZ05wMlBqa3FlWkt4bm1BaUcxeFY0b0hoOUFLTF9yU0su
          Qm9TVlBHWkhRdWtYblZqelJnU3VRcUduNzVOTDd5ZmtRY3l5NyIsICJwcm4iOiAibXlAZW1haWwu
          Y29tIiwgImF1ZCI6ICJodHRwczovL2xvZ2luLnNhbGVzZm9yY2UuY29tIiwgImV4cCI6ICIxMzMz
          Njg1NjI4In0=
    ```
6. Download the X509 Certificate from the JKS.
7. Sign the resulting string using RSA SHA256.
8. Create a string of the string from step 5. Create the string in this format.
    
    ```
    existing_string + "." + base64_encoded_signature
    ```
    
    In this example, the base64 encoded signature is highlighted.
    
    ```
    eyJhbGciOiJSUzI1NiJ9.eyJpc3MiOiAiM01WRzk5T3hUeUVNQ1EzZ05wMlBqa3FlWkt4bm1BaUcxeFY0b0hoOUFLTF9yU0su
          Qm9TVlBHWkhRdWtYblZqelJnU3VRcUduNzVOTDd5ZmtRY3l5NyIsICJwcm4iOiAibXlAZW1haWwu
          Y29tIiwgImF1ZCI6ICJodHRwczovL2xvZ2luLnNhbGVzZm9yY2UuY29tIiwgImV4cCI6ICIxMzMz
          Njg1NjI4In0=.iYCthqWCQucwi35yFs-nWNgpF5NA_a46fXDTNIY8ACko6BaEtQ9E6h4Hn1l_pcwcK​
          I_GlmfUO2dJDg1A610t09TeoPagJsZDm_H83bsoZUoI8LpAA1s-2aj_Wbysqb1j4uDToz​
          480WtEbkwIv09sIeS_-QuWak2RXOl1Krnf72mpVGS4WWSULodgNzlKHHyjAMAHiBHIDNt​
          36y2L2Bh7M8TNWiKa_BNM6s1FNKDAwHEWQrNtAeReXgRy0MZgQY2rZtqT2FcDyjY3JVQb​
          En_CSjH2WV7ZlUwsKHqGfI7hzeEvVdfOjH9NuaJozxvhPF489IgW6cntPuT2V647JWi7ng
    ```
    
    Use the signed JWT in the `client_assertion` parameter when you configure headless flows using the OAuth 2.0 for First-Party Applications standard.