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

# Chat Authentication

Chat authentication is handled by the underlying Pub/Sub SDK. You authenticate an Ably Realtime client, then pass that authenticated client into `ChatClient`.

## Authentication Flow

1. Your auth server authenticates the user
2. Your auth server issues an Ably-compatible token (JWT format is recommended for most apps)
3. The client SDK fetches tokens with `authCallback` and refreshes them automatically before expiry
4. The authenticated Pub/Sub client is passed into `ChatClient`

## Server Setup

Create an endpoint that validates user-provided credentials and returns JWTs with the appropriate Chat capabilities:

<Tabs>
  <Tab name="JavaScript">
    <Code>
      ```javascript theme={null}
      import jwt from 'jsonwebtoken';

      const [keyName, keySecret] = process.env.ABLY_API_KEY.split(':');

      const ablyJwt = jwt.sign(
        {
          'x-ably-capability': JSON.stringify({
            'your-room': ['publish', 'subscribe', 'presence', 'history'],
          }),
          'x-ably-clientId': userId,
        },
        keySecret,
        { algorithm: 'HS256', keyid: keyName, expiresIn: '1h' }
      );
      ```
    </Code>
  </Tab>

  <Tab name="Python">
    <Code>
      ```python theme={null}
      import jwt
      import json
      import time
      import os

      key_name, key_secret = os.environ['ABLY_API_KEY'].split(':')

      now = int(time.time())
      ably_jwt = jwt.encode(
          {
              'iat': now,
              'exp': now + 3600,
              'x-ably-capability': json.dumps({
                  'your-room': ['publish', 'subscribe', 'presence', 'history'],
              }),
              'x-ably-clientId': user_id,
          },
          key_secret,
          algorithm='HS256',
          headers={'kid': key_name}
      )
      ```
    </Code>
  </Tab>
</Tabs>

## Client Setup

<Tabs>
  <Tab name="JavaScript">
    <Code>
      ```javascript theme={null}
      import * as Ably from 'ably';
      import { ChatClient } from '@ably/chat';

      const realtimeClient = new Ably.Realtime({
        authCallback: async (tokenParams, callback) => {
          try {
            const response = await fetch('/api/ably-token', { credentials: 'include' });
            if (!response.ok) throw new Error('Auth failed');
            const jwt = await response.text();
            callback(null, jwt);
          } catch (error) {
            callback(error, null);
          }
        },
      });

      const chatClient = new ChatClient(realtimeClient);
      ```
    </Code>
  </Tab>

  <Tab name="React">
    <Code>
      ```react theme={null}
      import { useMemo } from 'react';
      import * as Ably from 'ably';
      import { ChatClient } from '@ably/chat';
      import { ChatClientProvider } from '@ably/chat/react';

      export function App() {
        const realtimeClient = useMemo(
          () =>
            new Ably.Realtime({
              authCallback: async (tokenParams, callback) => {
                try {
                  const response = await fetch('/api/ably-token', { credentials: 'include' });
                  if (!response.ok) throw new Error('Auth failed');
                  callback(null, await response.text());
                } catch (error) {
                  callback(error, null);
                }
              },
            }),
          []
        );

        const chatClient = useMemo(() => new ChatClient(realtimeClient), [realtimeClient]);

        return (
          <ChatClientProvider client={chatClient}>
            <YourChatUI />
          </ChatClientProvider>
        );
      }
      ```
    </Code>
  </Tab>
</Tabs>

## Chat Capabilities

Capabilities are permissions that control what operations a client can perform:

| Feature           | Required Capabilities                                   |
| ----------------- | ------------------------------------------------------- |
| Send messages     | `publish`                                               |
| Receive messages  | `subscribe`                                             |
| Update messages   | `message-update-any` or `message-update-own`            |
| Delete messages   | `message-delete-any` or `message-delete-own`            |
| Message history   | `subscribe`, `history`                                  |
| Message reactions | `annotation-publish`, optionally `annotation-subscribe` |
| Presence          | `subscribe`, `presence`                                 |
| Typing indicators | `publish`, `subscribe`                                  |
| Room reactions    | `publish`, `subscribe`                                  |
| Occupancy         | `subscribe`, `channel-metadata`                         |

## Room-scoped Capabilities

You can scope capabilities to specific rooms, a namespace of rooms, or all rooms:

* `my-chat-room` - a specific room
* `dms:*` - all rooms in the `dms:` namespace
* `*` - all chat rooms

## Next Steps

* Learn about [connections](/docs/chat/connections)
* Start building with [rooms](/docs/chat/rooms)
* Explore [message features](/docs/chat/rooms/messages)
