Spaces authentication

Open in

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

How Spaces maps to channels

A logical space is implemented using underlying Pub/Sub channels. Capability expressions should account for both channel types:

  • Main space channel: your-space (presence and member locations)
  • Cursors channel: your-space-cursors (high-frequency cursor updates)

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 Spaces.

Server setup

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

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

// Server-side JWT with space-scoped capabilities
import jwt from 'jsonwebtoken';

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

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

Client setup

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

import Spaces from '@ably/spaces';
import { Realtime } from 'ably';

const realtimeClient = new 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 spaces = new Spaces(realtimeClient);

In each example, the authenticated Pub/Sub client is passed into Spaces and Spaces uses that connection for authentication and token renewal.

Spaces capabilities

Feature areaRequired capabilities
Member locations and avatar stacksubscribe, presence
Live cursorspublish, subscribe
Component lockingsubscribe, presence
History-aware collaborationhistory

Space-scoped capabilities

You can scope capabilities to specific spaces or all spaces:

  • my-space - a specific space and its associated channels
  • my-namespace:* - all spaces in the my-namespace: namespace
  • * - all spaces

Token lifecycle and permission updates

  • With authCallback or authUrl, token refresh is automatic and handled by the SDK.
  • To change a user's capabilities during an active session, issue a new token from your auth server and re-authenticate:
JavaScript

1

2

// Re-authenticate to pick up updated capabilities
await realtimeClient.auth.authorize();