# Identity verification

> Securely tell the agent who the signed-in visitor is from the embedded widget. Sign the user id on your server with HMAC-SHA256, call window.bookbag.identify(), and the agent recognizes the customer, auto-syncs a contact, and personalizes replies.

If your visitors are already signed in to your site, you can tell the embedded agent who they are. To stop anyone impersonating a user, you sign the user's id on your **server** with an HMAC, and the widget forwards that signature with every message. Bookbag verifies it, recognizes the customer, syncs a [contact](/docs/contacts/overview), and personalizes the conversation.

> **NEVER COMPUTE THE HASH IN THE BROWSER:** The hash must be generated on your server with your agent's secret key. If you put the secret in client-side JavaScript, anyone can read it and impersonate any user.

## How it works

- On your server, compute `user_hash = HMAC-SHA256(user_id)` using your agent's **signing secret**.
- On the page, call `window.bookbag('identify', { user_id, user_hash, user_metadata })`.
- The widget attaches `user_id`, `user_hash`, and `user_metadata` to every chat request; Bookbag verifies the hash and trusts the identity.

## Your signing secret

Each agent has its own signing secret. Open your agent → **Chat Interface → Embed → Identity verification**, click **Reveal**, and copy it. You can **Rotate** it at any time (the old secret stops working immediately). Store it as a server-side environment variable.

## 1. Sign the user id on your server

```javascript
const crypto = require("crypto");
const secret = process.env.BOOKBAG_SECRET; // your agent's signing secret
const userId = String(currentUser.id);
const userHash = crypto.createHmac("sha256", secret).update(userId).digest("hex");
```

## 2. Identify the user in the browser

Render the server-computed values into the page, then call `identify`:

```javascript
window.bookbag("identify", {
  user_id: "user-123",
  user_hash: "the-hash-from-your-server",
  user_metadata: {
    name: "Jane Doe",
    email: "jane@example.com",
    plan: "growth"   // any extra keys become contact custom attributes
  }
});
```

> **RE-IDENTIFY ON SIGN IN/OUT:** Call `identify` again after the user signs in or out. The widget always uses the most recent identity, and clears it if you call `identify(null)`.

## What identity unlocks

- **Contact auto-sync** — on a verified chat, Bookbag upserts the [contact](/docs/contacts/overview) whose `external_id` equals `user_id`, filling name/email/phone and turning any extra `user_metadata` keys into [custom attributes](/docs/contacts/custom-attributes). Return visits update the same record.
- **Personalized answers** — the agent receives the contact's known details and can greet the customer by name and tailor replies without re-asking.
- **Action context** — actions can reference the verified customer with `{{contact.email}}`, `{{contact.name}}`, `{{contact.external_id}}`, and `{{contact.attr.<key>}}`.

## 3. Require verified identity (optional)

By default the agent accepts both anonymous and verified visitors. Turn on **Require verified identity** (Chat Interface → Embed → Identity verification) to **reject any chat** that isn't signed. Bookbag recomputes `HMAC-SHA256(user_id)` with your secret and compares it to the `user_hash` the widget sent; a missing or wrong hash is refused with `401 identity_unverified`.

> **TURN IT ON ONLY AFTER WIRING IDENTIFY():** If you require verified identity before your site calls `identify()` with a valid hash, all chats are rejected. Roll it out: ship `identify()` first, confirm it works, then require it.

## Shopify

On Shopify the storefront integration identifies the logged-in customer for you from a theme-injected `window.__bbCustomer`. See the [Shopify integration](/docs/integrations/shopify).

- [Contacts overview](/docs/contacts/overview) — The records identity syncs into, and how the agent uses them.
- [JavaScript embed & SDK](/docs/developers/javascript-embed) — Install the widget and the window.bookbag global.
- [Custom attributes](/docs/contacts/custom-attributes) — Typed fields your user_metadata maps onto.
