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

# User identification

> Link conversations to users in your system

User identification lets you securely pass user information to the chat widget. This enables personalized conversations, linking chats to your user records, and showing user context to your support team.

## How it works

```
┌─────────────────┐     ┌─────────────────┐     ┌─────────────────┐
│  Your backend   │     │  Your frontend  │     │    Replyful     │
└────────┬────────┘     └────────┬────────┘     └────────┬────────┘
         │                       │                       │
         │  1. Generate token    │                       │
         │<──────────────────────│                       │
         │                       │                       │
         │  2. Return signed JWT │                       │
         │──────────────────────>│                       │
         │                       │                       │
         │                       │  3. replyful.identify │
         │                       │──────────────────────>│
         │                       │                       │
         │                       │  4. Verify & link     │
         │                       │<──────────────────────│
```

1. Your frontend requests a token from your backend
2. Your backend generates a signed JWT using your Identity Secret
3. Your frontend passes the token to the widget
4. Replyful verifies the token and links the conversation to the user

## Get your identity secret

1. Go to your [Replyful dashboard](https://app.replyful.com)
2. Navigate to **Settings** → **Security**
3. Copy your **Identity Secret**

<Warning>
  Keep your Identity Secret secure. Never expose it in client-side code.
</Warning>

## Generate a token on your backend

Create an API endpoint that generates a signed JWT for authenticated users.

<Tabs>
  <Tab title="Node.js">
    Install the `jsonwebtoken` package:

    ```bash theme={null}
    npm install jsonwebtoken
    ```

    Create a token endpoint:

    ```javascript theme={null}
    import jwt from 'jsonwebtoken';

    const IDENTITY_SECRET = process.env.REPLYFUL_IDENTITY_SECRET;

    function generateReplyfulToken(user) {
      return jwt.sign(
        {
          // Required
          userId: user.id,

          // Optional
          email: user.email,
          name: user.name,

          // Custom properties (visible to your support team)
          plan: user.subscription?.plan,
          company: user.company?.name,
        },
        IDENTITY_SECRET,
        {
          expiresIn: '1h',
          algorithm: 'HS256'
        }
      );
    }

    // Express example
    app.get('/api/replyful-token', authenticate, (req, res) => {
      const token = generateReplyfulToken(req.user);
      res.json({ token });
    });
    ```
  </Tab>

  <Tab title="PHP">
    Install the `firebase/php-jwt` package:

    ```bash theme={null}
    composer require firebase/php-jwt
    ```

    Create a token endpoint:

    ```php theme={null}
    <?php
    use Firebase\JWT\JWT;

    $identitySecret = getenv('REPLYFUL_IDENTITY_SECRET');

    function generateReplyfulToken($user) {
        global $identitySecret;

        $payload = [
            'userId' => $user->id,        // Required
            'email' => $user->email,      // Optional
            'name' => $user->name,        // Optional
            'plan' => $user->plan,        // Custom property
            'exp' => time() + 3600        // 1 hour expiration
        ];

        return JWT::encode($payload, $identitySecret, 'HS256');
    }

    // API endpoint example
    if ($_SERVER['REQUEST_METHOD'] === 'GET' && $_SERVER['REQUEST_URI'] === '/api/replyful-token') {
        // Ensure user is authenticated
        $user = getCurrentUser();
        if (!$user) {
            http_response_code(401);
            exit;
        }

        header('Content-Type: application/json');
        echo json_encode(['token' => generateReplyfulToken($user)]);
    }
    ```
  </Tab>
</Tabs>

## Call identify from your frontend

After a user logs in, fetch the token from your backend and pass it to the widget:

```javascript theme={null}
async function identifyUser() {
  const response = await fetch('/api/replyful-token', {
    credentials: 'include'
  });
  const { token } = await response.json();

  replyful('identify', { token });
}

// Call after user logs in
identifyUser();
```

### React example

```jsx theme={null}
import { useEffect } from 'react';
import { useUser } from './auth';

function ReplyfulIdentify() {
  const { user, isAuthenticated } = useUser();

  useEffect(() => {
    if (!isAuthenticated) return;

    async function identify() {
      const res = await fetch('/api/replyful-token');
      const { token } = await res.json();
      window.replyful?.('identify', { token });
    }

    identify();
  }, [isAuthenticated, user?.id]);

  return null;
}
```

## Token payload

| Field    | Type   | Required | Description                            |
| -------- | ------ | -------- | -------------------------------------- |
| `userId` | string | Yes      | Unique identifier in your system       |
| `email`  | string | No       | User's email address                   |
| `name`   | string | No       | User's display name                    |
| `*`      | any    | No       | Custom properties (visible to support) |

## Security best practices

1. **Never expose your Identity Secret** in client-side code
2. **Generate tokens server-side only** to prevent tampering
3. **Use short expiration times** (1 hour recommended)
4. **Authenticate users** before generating tokens
5. **Use HTTPS** for all API requests

The widget handles missing or invalid tokens gracefully — users can still chat anonymously.
