
In the digital age, understanding and engaging with your customers on a personalized level has become a pivotal factor in business success. Synerise provides an efficient solution to this with its advanced tracking capabilities. By implementing the authorization of events with the Synerise tracking script, businesses can open doors to a plethora of opportunities. 

Employing JWT (JSON Web Tokens) authentication for these events ensures data security, giving businesses the confidence in knowing their customer data is protected. JWT, being a compact and self-contained way for securely transmitting information, is an industry-standard for authorization. Synerise's insistence on using JWT with the RS256 algorithm provides an additional layer of security. 

In essence, authorizing events with Synerise is not just about sending and receiving data. It's about transforming the way businesses interact with their customers, providing them with unique, personalized experiences, all the while ensuring the utmost data security. This integration is an essential step for companies aiming for growth, increased customer satisfaction, and improved ROI. 

In our step-by-step guide to authorizing events with Synerise, we'll be leveraging two prominent technologies: Python Flask and JavaScript React. Flask is a lightweight web framework for Python, ideal for creating small to medium-sized web applications with ease and efficiency. On the other hand, React is a renowned JavaScript library developed by Facebook, designed for building user interfaces in a modular and reactive manner. Together, Flask will power our backend, providing necessary endpoints and logic, while React will drive our frontend, ensuring a seamless user experience. This combination allows for a robust and scalable solution, optimized for both development and production scenarios. 

After you complete this integration and your website is ready to authorize events with JWT, you can start requiring authorization for sensitive events. For details on enabling JWT requirements for events, see ["Event authentication settings"](/docs/assets/events/event-settings).

<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>

## Prerequisites 
---
- Public RSA key added to Synerise. If keys were not added before, check how you can add them [here](/developers/web/jwt-auth#prerequisites). 
- Local machine with installed Python and Node environments.
- Tracking code added to your React website.
- Basic skills in React and Python.

## Process
---
The logic is described in [Authenticating requests with JSON Web Tokens (JWT)](/developers/web/jwt-auth) and this use case presents an example implementation step by step. 

1. [Implement back-end](/use-cases/anonymous-profile-to-recognized#implement-back-end)
2. [Implement front-end](/use-cases/anonymous-profile-to-recognized#implement-front-end)

## Implement back-end
---

Before creating the front-end, we must create a backend—our bridge to the Synerise platform. The PyJWT and cryptography libraries ensure that a secure JWT is created according to Synerise's standards. The primary endpoint, **/generate-jwt** (created with Flask), facilitates this by generating a JWT from customer data. 

### Install libraries

Using the `pip install Flask PyJWT cryptography` command, install three Python packages: Flask, PyJWT, and cryptography. 

Explanation of these packages:
- **[Flask](https://flask.palletsprojects.com/en/3.0.x/)** - Lightweight web framework for Python. We will use it to create the web server and define the API endpoint to generate JWT and return it to our React application. 
- **[PyJWT](https://pyjwt.readthedocs.io/en/stable/)** - Python library which allows encoding and decoding JSON Web Tokens (JWT). 
- **[cryptography](https://github.com/pyca/cryptography)** - Python library that offers secure cryptographic operations, essential for RS256 algorithm support in generating JWTs in our project. 


  <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">

  When developing any Python application, it’s a best practice to use virtual environments! Virtual environments allow you to create isolated Python environments for different projects, avoiding conflicts between dependencies.

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


### Implement the Flask application

The application imports the private RSA key, which is needed to sign the JWT.  
The **/generate-jwt** endpoint of the application accepts POST requests with customer information (email and UUID) and uses that data to generate a JWT compliant with Synerise's requirements.  
Error handling is included in the code. To better understand the code, read the comments.


<pre><code class="language-python">from flask import Flask, jsonify, request 
import jwt 
import datetime

app = Flask(__name__)

# Load the RSA private key for JWT signing. 
# Synerise requires JWTs to be signed with RSA. 

with open('private.pem', 'r') as f: 
    PRIVATE_KEY = f.read() 

@app.route('/generate-jwt', methods=['POST']) 
def generate_jwt(): 

    """ 
    Endpoint to generate JWT using the RS256 algorithm, as required by Synerise. This method expects a JSON payload containing the "email" and "uuid" of a customer. 
    """ 

    # Retrieve the JSON payload from the request 

    data = request.get_json() 

    # Ensure both 'email' and 'uuid' are present in the request 
    # As per documentation, the JWT payload should include customer's email and UUID. 

    if not data or 'email' not in data or 'uuid' not in data: 
        return jsonify({'error': 'Missing email or uuid in request'}), 400 

    email = data['email'] 
    uuid = data['uuid'] 

    # JWT header as defined in the documentation 
    # Synerise requires the JWT to use the RS256 algorithm. 

    headers = { 
        "alg": "RS256", 
        "typ": "JWT" 
    } 

    # JWT payload as per Synerise's requirements 

    payload = { 
        "exp": datetime.datetime.utcnow() + datetime.timedelta(days=7),  # Token expiry set to 7 days as stated in the documentation 
        "uuid": uuid,   # customer's UUID 
        "email": email  # customer's email 
    } 

    # Generate the JWT token 
    # The token is signed with the RSA private key as required by the documentation. 
    token = jwt.encode(payload, PRIVATE_KEY, algorithm="RS256", headers=headers) 


    return jsonify({'jwt': token}) 

 
if __name__ == '__main__': 

    # Start the Flask application 

    app.run(debug=True)</code></pre>


## Implement front-end
---

The front-end part is modular to ensure efficiency and easier maintenance.

The **useSyneriseAuthentication** hook creates an UUIDv5 for the customer and uses it in the request for a JWT. 

Next, the hook is used in the **LoginForm** component, which collects the customer's email that's passed to the hook for creating a JWT.
To better understand the code, read the comments.

### Implement custom authentication hook


<pre><code class="language-java">import { useState } from 'react'; 


/** 
 * Custom hook to handle Synerise authentication. 
 */ 
function useSyneriseAuthentication() { 
    const [loading, setLoading] = useState(false); 
    const [error, setError] = useState(null); 

 
    // Function to generate UUIDv5 based on a salt and unique identifier 
    const generateUUIDv5 = (uniqueIdentifier) =&gt; { 
        const salt = "someString"; 
        return uuid.uuid5(uuid.NAMESPACE_URL, (salt + uniqueIdentifier)); 
    }; 

 
    // Function to fetch JWT from the backend 
    const fetchJWT = async (email, uuidValue) =&gt; { 
        const response = await fetch('/generate-jwt', { 
            method: 'POST', 
            headers: { 
                'Content-Type': 'application/json', 
            }, 
            body: JSON.stringify({ email, uuid: uuidValue }), 
        }); 


        if (!response.ok) { 
            throw new Error("Failed to fetch JWT"); 
        } 

 
        const { jwt } = await response.json(); 
        return jwt; 
    }; 

 
    // Function to authenticate a user with Synerise 
    const authenticate = async (email) =&gt; { 
        setLoading(true); 
        setError(null); 

 
        try { 
            const existingIdentityHash = SR.client.getIdentityHash(); 
            const hashedEmail = SR.client.hashIdentity(email); 

            let uuidValue; 

            if (!existingIdentityHash || hashedEmail !== existingIdentityHash) { 
                uuidValue = generateUUIDv5(email); // Derive from a cookie in a real-world scenario 

                const jwt = await fetchJWT(email, uuidValue); 
                SR.client.setUuidAndidentityHash(hashedEmail, uuidValue); 
                SR.client.setAccessToken(jwt); 
            } else { 
                // Identity matches the current customer; Continue with the existing JWT 
                // This can be enhanced based on specific requirements 
            } 

            setLoading(false); 
        } catch (err) { 
            setError(err.message); 
            setLoading(false); 
        } 
    }; 

 
    return { authenticate, loading, error }; 
} 


export default useSyneriseAuthentication;</code></pre>


### Implement LoginForm component

Below you can find the example of useSyneriseAuthentication usage:


<pre><code class="language-java">import { useState } from 'react'; 
import useSyneriseAuthentication from './useSyneriseAuthentication'; // Ensure you've created this hook as mentioned earlier. 


function LoginForm() { 
    const [email, setEmail] = useState(''); 
    const syneriseAuth = useSyneriseAuthentication(); 


    const handleSubmit = async (event) =&gt; { 
        event.preventDefault(); 

 
        // Initiate authentication process using the provided email 
        const success = await syneriseAuth.authenticate(email); 

 
        if (success) { 
            console.log("Authentication successful."); 
            // Here, you can redirect or update the UI as necessary. 
        } else { 
            console.log("Authentication failed."); 
            // Handle failure, maybe show an error message or retry. 
        } 
    }; 

 
    return ( 
        &lt;div&gt; 
            &lt;h2&gt;Login&lt;/h2&gt; 
            &lt;form onSubmit={handleSubmit}&gt; 
                &lt;div&gt; 
                    &lt;label&gt;Email:&lt;/label&gt; 
                    &lt;input  
                        type="email"  
                        value={email}  
                        onChange={e =&gt; setEmail(e.target.value)}  
                        required 
                    /&gt; 
                &lt;/div&gt; 
                &lt;div&gt; 
                    &lt;button type="submit"&gt;Login&lt;/button&gt; 
                &lt;/div&gt; 
            &lt;/form&gt; 
        &lt;/div&gt; 
    ); 
} 


export default LoginForm;</code></pre>


Test the solution and adapt it to fit your specific needs. For example, we recommend adding authentication on your website before a visitor can request the JWT and start sending events.

## What's next
---
Send events from your website as described in ["Event tracking"](/developers/web/event-tracking).  

## Read more
---
[Introduction to events](/docs/assets/events/introduction-to-events). 
