# Authentication

Security
Access Tokens expire after **30 minutes**. Always generate a fresh token server-side immediately before loading an Element. Never expose your API key in client-side code.

All of our components are authenticated using Access Tokens.  These Access Tokens are short-lived tokens that must be obtained immediately before loading the relevant web component.

## Access Token

To generate an Access Token, you can utilize the Hero Health Public API. To do so, it's necessary to create an endpoint on your server that securely interacts with the Hero Health Public API for Access Token generation. This endpoint should enforce robust authentication measures and restrict access solely to authenticated users within your system.

img
Note that if your application uses a server-side rendered approach, you can call the Hero Health Public API to generate an Access Token directly, as long as it does not come from the frontend.

### Admin context

For Elements that enable writeback into the clinical record (e.g. consultation, messaging, inbox), you may want to provide admin context into the Element to ensure that the author on the writeback matches the user performing those actions.

In order to do this, you will need to pass the user's corresponding Hero admin ID into the `x-admin-id` header on generation of the Access Token to ensure that this context is available within the Element.  The user will also need to hold sufficient RBAC permissions to perform a writeback.

In the absence of this header, the system will fall back to the default partner user (as set up during partner onboarding), or failing that the default Hero service user for the integration (as set up by the practice during practice onboarding).

Here is an example of an endpoint to retrieve the Access Token from Hero Health Public API.

```jsx
const express = require('express');
const fetch = require('node-fetch');

const app = express();
const PORT = process.env.PORT || 3000;

// Define your Hero Health API credentials
const API_KEY = 'YOUR_API_KEY';
const PRACTICE_GROUP_ID = 'YOUR_PRACTICE_GROUP_ID';
const ADMIN_ID = 'YOUR_HERO_ADMIN_ID';

// Define the endpoint to retrieve the Access Token
app.get('/get-access-token', async (req, res) => {
    // Make sure only authenticated users can access the endpoint
    if (!req.user) {
        res.status(401);
    }
    try {
        // Make a request to Hero Health Public API to generate the Access Token
        const response = await fetch('https://api.herohealth.net/v1/access_token', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'x-api-key': API_KEY,
                'x-practice-group-id': PRACTICE_GROUP_ID,
                'x-admin-id': ADMIN_ID // optional
            },
        });

        if (!response.ok) {
            throw new Error('Failed to generate Access Token');
        }

        const data = await response.json();
        const accessToken = data.access_token;

        // Return the Access Token as a response
        res.json({ access_token: accessToken });
    } catch (error) {
        console.error('Error retrieving Access Token:', error);
        res.status(500).json({ error: 'Internal Server Error' });
    }
});

// Start the server
app.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}`);
});
```

Check the documentation for the “Create Access Token” operation on Hero Health Public API.

## How to implement

### 1. Include the script tag

```jsx
<script src="https://scripts.htech.app/message-builder/web-component/latest.js"></script>
```

### 2. Render the Web Component

You'll need to write a script to render the Web Component when you receive the Access Token from the server. This can be accomplished in various ways, but you can refer to the example below:

```html
<div id="message-builder-container"></div>

<script>
    // Function to retrieve the Access Token from the server
    function getAccessToken() {
        // Make an AJAX request to your server endpoint to retrieve the Access Token
        // Replace 'YOUR_SERVER_ENDPOINT' with your actual endpoint URL
        fetch('YOUR_SERVER_ENDPOINT')
            .then(response => response.json())
            .then(data => {
                const accessToken = data.access_token;
                // Display the Web Component after retrieving the Access Token
                displayMessageBuilder(accessToken);
            })
            .catch(error => {
                console.error('Error fetching Access Token:', error);
            });
    }

    // Function to display the Hero Health Message Builder Web Component
    function displayMessageBuilder(accessToken) {
        // Create a new instance of the Web Component
        const messageBuilderComponent = document.createElement('hh-message-builder');
        // Set the 'jwt-token' prop with the retrieved Access Token
        messageBuilderComponent.setAttribute('jwt-token', accessToken);
        // Append the Web Component to the container element
        document.getElementById('message-builder-container').appendChild(messageBuilderComponent);
    }

    // Call the function to retrieve the Access Token when the page loads
    window.onload = function() {
        getAccessToken();
    };
</script>
```

### Server-side rendered pages

Suppose you are using a server-side rendering approach in your application. In that case, you can retrieve the access token on render time and inject it directly into the Message Builder component.

Be aware that the Access Token expires in 30 minutes, so caching strategies can lead to authentication errors.

```jsx
const express = require('express');
const fetch = require('node-fetch');

const app = express();
const PORT = process.env.PORT || 3000;

// Define your Hero Health API credentials
const API_KEY = 'YOUR_API_KEY';
const PRACTICE_GROUP_ID = 'YOUR_PRACTICE_GROUP_ID';

// Define a function to fetch the Access Token from the Hero Health Public API
async function getAccessToken() {
    try {
        // Make a request to Hero Health Public API to generate the Access Token
        const response = await fetch('https://api.herohealth.net/v1/access_token', {
            method: 'POST',
            headers: {
                'Content-Type': 'application/json',
                'x-api-key': API_KEY,
                'x-practice-group-id': PRACTICE_GROUP_ID
            },
        });

        if (!response.ok) {
            throw new Error('Failed to generate Access Token');
        }

        const data = await response.json();
        const accessToken = data.access_token;

        return accessToken;
    } catch (error) {
        console.error('Error retrieving Access Token:', error);
        throw error;
    }
}

// Define a route to render the web component after getting the Access Token
app.get('/render-component', async (req, res) => {
    try {
        // Retrieve the Access Token
        const accessToken = await getAccessToken();

        // Render the web component with the Access Token
        const html = `
            <!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
                <title>Rendered Component</title>
                <script src="https://scripts.htech.app/message-builder-component/latest.js"></script>
            </head>
            <body>
                <hh-message-builder jwt-token="${accessToken}"></hero-health-message-builder>
            </body>
            </html>
        `;

        res.send(html);
    } catch (error) {
        res.status(500).send('Internal Server Error');
    }
});

// Start the server
app.listen(PORT, () => {
    console.log(`Server is running on http://localhost:${PORT}`);
});
```