> ## Documentation Index
> Fetch the complete documentation index at: https://docs.proficientai.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> Use request headers for authentication

Authentication with the Client API is achieved with three request headers, one of which is optional depending on your project configuration.

## Headers

<ParamField query="X-PROFICIENT-API-KEY" type="string" required>
  The publishable API key associated with your project. You can find this in
  [Project Settings](https://proficientai.com/project-settings). It's a string
  that starts with `pk_`.
</ParamField>

<ParamField query="X-PROFICIENT-USER-EXTERNAL-ID" type="string" required>
  A string that uniquely identifies the user within your project. Ensure that
  this is the ID that you use to identify the user in your system e.g. database
  ID, Firebase Auth ID etc. Failing to do so may cause unexpected bugs and
  errors in your application.
</ParamField>

<ParamField query="X-PROFICIENT-USER-HMAC" type="string" optional>
  The HMAC hash for the user. See [HMAC Authentication](#hmac-authentication)
  for more details.
</ParamField>

Here is an example cURL request containing two auth headers:

<CodeGroup>
  ```bash cURL theme={null}
  curl --request GET \
    --url https://api.proficientai.com/interactions \
    --header 'X-PROFICIENT-API-KEY: pk_40NDqyJqjBe6DJyLn44HBEgi0loTunwLdjWHhcOUGONSkpomQx0qInkWLtu0ouwSr6qqE7HQ' \
    --header 'X-PROFICIENT-USER-EXTERNAL-ID: gtLIK8ELsHTr0Fajg28Ud9eFpJJ3'
  ```
</CodeGroup>

## HMAC Authentication

HMAC authentication is a mechanism that provides an additional layer of security to ensure your client
application can securely consume Proficient APIs. To enable HMAC authentication for a given project you
simply need to go the [Project Settings](https://proficientai.com/project-settings) page on the dashboard
and toggle it on.

Once HMAC authentication is enabled, all Client API endpoints will require a `X-PROFICIENT-USER-HMAC`
header, and the requests that don't include will be rejected with a `401` error.

<Warning>
  While HMAC authentication is optional, we strongly recommend enabling it for
  applications that have an authentication flow where user data is persisted
  into your system. Disabling HMAC may pose a security risk where an end user
  can access another user's data.
</Warning>

### Computing the HMAC hash

The [HMAC](https://en.wikipedia.org/wiki/HMAC) hash is a string generated with the [SHA-256](https://en.wikipedia.org/wiki/SHA-2) algorithm and
digested with [Base64](https://en.wikipedia.org/wiki/Base64). It is produced using your project's HMAC secret as key and your user's external ID
as message.

<Info>
  You can find the HMAC secret associated with your project in [Project
  Settings](https://proficientai.com/project-settings). It's a string that
  starts with `hsec_`.
</Info>

The HMAC hash needs to be computed in your backend for each user. You can set up a small backend service
(e.g. a Firebase Cloud Function or AWS Lambda) where you authenticate your user and then proceed to
compute the hash with their unique ID.

**Summarizing the entire flow:**

<Check>
  1. Your frontend sends a request to your backend with the user's external ID.
  2. Your backend authenticates the user using your authentication system.
  3. Your backend computes the hash and sends it back to your frontend.
  4. Your frontend can now access Proficient's Client API with an additional `X-PROFICIENT-USER-HMAC` header.
</Check>

### React + Node.js Example

Here is a simple example with a React application using the [React SDK](/react-sdk) for
the frontend and a Node.js/Express application for the backend.

<CodeGroup>
  ```tsx App.tsx theme={null}
  import { InteractionView } from "@proficient/react";
  import axios from "axios";

  async function retrieveHmacHash(userExternalId: string) {
    type Response = {
      hmac: string;
    };
    const serverBaseUrl = "http://example.com"; // Replace with your own
    const { data } = await axios.request<Response>({
      baseURL: `${serverBaseUrl}/hmac`,
      data: { userExternalId },
      headers: {
        "Content-Type": "application/json",
      },
    });
    return data.hmac;
  }

  export default function App() {
    // Agent ID can be hardcoded or retrieved from the API
    const agentId = "ag_Lad8YCGGiDLiqIZPWRXmc2ix";
    // User external ID should be accessed dynamically
    const userExternalId = "gtLIK8ELsHTr0Fajg28Ud9eFpJJ3";
    return (
      <div>
        <InteractionView
          // Your publishable API key that starts with `pk_`
          apiKey={process.env.PROFICIENT_API_KEY}
          agentId={agentId}
          userExternalId={userExternalId}
          userHmac={() => retrieveHmacHash(userExternalId)}
        />
      </div>
    );
  }
  ```

  ```ts server.ts theme={null}
  import { createHmac } from "crypto";
  import * as express from "express";

  // This should most likely go into your environment secrets.
  // Store it securely in your backend and never expose it in the client.
  const HMAC_SECRET =
    "hsec_mFLSkjGK6XLK1TUxL8wgiXrjwZCqcfmgbXTC0JmZFooSl9rQlzIrpsQHNor4guw2YOUP7vWA";

  const app = express();

  app.use(express.json());

  app.post("/hmac", (req, res) => {
    const { userExternalId } = req.body;
    // Use your authentication system to authenticate the user request.
    const isAuthorized = true;
    if (!isAuthorized) {
      res.status(401).send({ message: "Unauthorized" });
      return;
    }
    const hmacHash = createHmac("sha256", HMAC_SECRET)
      .update(userExternalId)
      .digest("base64");
    // --> "nyrKK9qcWqgPSdky2VE+arkyJjMFt9FD1Fxl/iNOD5U="
    res.status(200).send({ hmac: hmacHash });
  });

  app.listen(8080, () => console.log(`Running on port 8080`));
  ```
</CodeGroup>
