
[JSON Web Tokens (JWT)](https://jwt.io/) can be used to authenticate JS SDK requests from recognized customers. This provides a way to identify customers before authorizing requests that modify personal data.  


<div class="admonition admonition-tip"><div class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" /></svg></div><div class="admonition-body"><div class="admonition-content">

See implementation of event authorization with JWT in [Event authorization in JS SDK with Flask](/use-cases/anonymous-profile-to-recognized).

</div></div></div>


By default, the `form.submit` events require JWT authentication. If you want to enable this for other events, see [Event authentication settings](/docs/assets/events/event-settings).

The tokens are generated by your backend.

Synerise requires a JWT encoded with the RS256 algorithm (this is **not** the default algorithm used by the [jwt.io debugger](https://jwt.io/)).


<div class="admonition admonition-important"><div class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg></div><div class="admonition-body"><div class="admonition-content">

JWTs created for use with Web SDK can't be used to authenticate API requests. This is a different type of authentication.

</div></div></div>


## Prerequisites:
A public RSA key must be added to Synerise.

<details class="accordion"><summary>If keys were not added before, expand and follow the procedure before you continue</summary><div class="accordion-content"><ol start="2"> <li><p>Go to <img src="/api/docs/image/54176ad07f146575310749eba44b7c2f42c1b327/icons/data-modeling-hub-icon.svg" alt="Data Modeling Hub icon" class="icon"> <strong>Data Modeling Hub &gt; Events</strong>.</p> </li> <li><p>On the <strong>JS SDK event settings</strong> tab, in the <strong>Certificate</strong> section, click <strong>Define</strong>.</p> </li> <li><p>If a certificate is already added, perform one of the following actions</p> <ul> <li>Keep using the existing certificate, no further actions are required.</li> <li>Overwrite the existing certificate by continuing to step <strong>4</strong>.</li> </ul> <div class="admonition admonition-warning"><div class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-2.5L13.732 4c-.77-.833-1.964-.833-2.732 0L4.082 16.5c-.77.833.192 2.5 1.732 2.5z" /></svg></div><div class="admonition-body"><div class="admonition-content"> <p>Overwriting a certificate requires providing the new certificate in your backend implementation! JWT tokens signed with the old certificate are rejected!</p> </div></div></div> </li> <li><p>Open the terminal.</p> </li> <li><p>Generate public and private RSA keys by using these commands:</p> <ol> <li><code>openssl genpkey -out private.pem -algorithm RSA -pkeyopt rsa_keygen_bits:2048</code></li> <li><code>openssl pkcs8 -topk8 -inform pem -in private.pem -outform DER -nocrypt -out private.der</code></li> <li><code>openssl rsa -pubout &lt; private.pem &gt; public.pem</code></li> </ol> </li> <li><p>Perform one of the following actions:</p> <ul> <li>To enter the certificate as text, in the <strong>Certificate code</strong> field paste the certificate <strong>with the header and footer</strong>.<br> The header and footer are: <code>-----BEGIN PUBLIC KEY-----</code>; <code>-----END PUBLIC KEY-----</code></li> </ul> <div class="admonition admonition-important"><div class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg></div><div class="admonition-body"><div class="admonition-content"> <p>The pasted certificate cannot contain line breaks or spaces.</p> </div></div></div> <div class="admonition admonition-tip"><div class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M9.663 17h4.673M12 3v1m6.364 1.636l-.707.707M21 12h-1M4 12H3m3.343-5.657l-.707-.707m2.828 9.9a5 5 0 117.072 0l-.548.547A3.374 3.374 0 0014 18.469V19a2 2 0 11-4 0v-.531c0-.895-.356-1.754-.988-2.386l-.548-.547z" /></svg></div><div class="admonition-body"><div class="admonition-content"> <p>To open the certificate in the terminal, you can usually use <code>cat public.pem</code> in the root directory.</p> </div></div></div> <ul> <li>To upload the certificate as a file, click <strong>Upload Certificate &gt; Upload certificate code</strong> and select a file from your computer.</li> </ul> </li> <li><p>Click <strong>Apply</strong>.</p> </li> </ol></div></details>


## Implementation overview

This flowchart is a high-level overview of the JWT creation logic. Your implementation must cover all of these scenarios.

The details are described in [this section](#implementation-details).

<figure><img src="/api/docs/image/54176ad07f146575310749eba44b7c2f42c1b327/developers/web/_gfx/jwt-flow.svg" class="full" alt="Diagram that shows the logic of JWT authentication"><figcaption>Overview of JWT implementation logic</figcaption></figure>

## Implementation details

When a customer provides their email (for example, when logging in), generate a JWT for the customer.

The provided email is used as `customer_email` everywhere in this process.

### Check if identity hash exists

1. Initialize the JS SDK.
1. Check the current identity hash by calling the `SR.client.getIdentityHash()` method.
2. Depending on the result, continue to one of these procedures:
    1. If the method returns an empty string, the hash does not exist. Follow [this instruction](#if-an-identity-hash-does-not-exist).
    2. If the method returns a non-empty string, a hash exists. Follow [this instruction](#if-an-identity-hash-exists).

### If an identity hash does NOT exist
1. Generate an identity hash by calling the `SR.client.hashIdentity("customer_email")` method.
2. From the `_snrs_uuid` cookie, retrieve the customer's UUID.
3. Generate a JWT. In the payload, provide the `customer_email` and the UUID retrieved from the cookie.  
For details, see [this section](#generating-json-web-tokens-jwt).
4. Call the `SR.client.setUuidAndIdentityHash("email_hash", "customer_uuid")` method, where:
  - `email_hash` is the hash you generated earlier with `SR.client.hashIdentity("customer_email")`
  - `customer_uuid` is the customer UUID retrieved from the `_snrs_uuid` cookie and encoded in the JWT
  
  **Result:**  
  The customer can now send events that require JWT authentication.

### If an identity hash exists
1. Call the `SR.client.getIdentityHash()` method.
2. Call the `SR.client.hashIdentity("customer_email")` method.
3. Compare the returned values.
   - If the values are identical, the identity matches the current customer. Follow this [this instruction](#if-the-identity-matches-the-current-customer).
   - If the values are different, the identity does not match the current customer. Follow this [this instruction](#if-the-identity-does-not-match-the-current-customer).

#### If the identity matches the current customer

1. From the `_snrs_uuid` cookie, retrieve the customer's UUID.
3. Generate a JWT. In the payload, provide the `customer_email` and the UUID retrieved from the cookie.  
For details, see [this section](#generating-json-web-tokens-jwt).

**Result:**  
The customer can now send events that require JWT authentication.

#### If the identity does not match the current customer:

1. Generate a new UUIDv5 using the `customer_email`.  
For details, see [this section](/developers/web/uuids#generating-uuidv5).
2. Generate an identity hash by calling the `SR.client.hashIdentity("customer_email")` method.
3. Generate a JWT. In the payload, provide the `customer_email` and the UUID you generated.
For details, see [this section](#generating-json-web-tokens-jwt).
4. Call the `SR.client.setUuidAndIdentityHash("email_hash", "customer_uuid")` method, where:
  - `email_hash` is the hash you generated earlier with `SR.client.hashIdentity("customer_email")`
  - `customer_uuid` is the customer UUID retrieved from the `_snrs_uuid` cookie and encoded in the JWT  

**Result:**  
The customer can now send events that require JWT authentication.

### Generating JSON Web Tokens (JWT)


<div class="admonition admonition-note"><div class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M13 16h-1v-4h-1m1-4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg></div><div class="admonition-body"><div class="admonition-content">

For details on how to implement token creation and encoding, refer to the documentation of the language or framework you are using.

</div></div></div>

1. In the header, include the following data:  

   <pre><code class="language-json">{
   "alg": "RS256”,
   "typ": "JWT"
   }</code></pre>

2. In the payload, include the following data:  

   <pre><code class="language-json">{
   "exp": 1599737564, // expiry time as a UNIX timestamp, less than 7 days away
   "uuid": "af0a5e16-dc1f-5242-8b22-daf62c3cb78d", // customer's UUID
   "email": "customer.email@domain.com" // customer's email
   }</code></pre>

    
   <div class="admonition admonition-important"><div class="admonition-icon"><svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2.5"><path stroke-linecap="round" stroke-linejoin="round" d="M12 8v4m0 4h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" /></svg></div><div class="admonition-body"><div class="admonition-content">

   The token lifetime cannot be longer than 7 days.

   </div></div></div>

1. Sign the token with the public and private keys.
2. Encode the token.
2. Apply the encoded token in one of the following ways:
    - Store the token in the `_snrs_token` cookie.
    - Call the `SR.client.setAccessToken("token-as-a-string")` [JS SDK method](/developers/web/methods-reference#authentication-by-json-web-token-jwt).  

    **Result:**  
    The JWT is stored as `snr-token` in local storage. If you applied the token by using a cookie, the cookie is deleted.

**You may want to return to:**
- [The identity hash does not exist](#if-an-identity-hash-does-not-exist)
- [The identity hash matched the current customer](#if-the-identity-matches-the-current-customer)
- [The identity hash did not match the current customer](#if-the-identity-does-not-match-the-current-customer)