Skip to content
Open
13 changes: 13 additions & 0 deletions src/pages/docs/auth/identified-clients.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,19 @@ When a client is assigned a trusted identity, that is, a `clientId`, then they a

For example, assume you are building a chat application and want to allow clients to publish messages and be present on a channel. If each client is assigned a trusted identity by your server, such as a unique email address or UUID, then all other subscribed clients can trust any messages or presence events they receive in the channel as being from that client. No other clients are permitted to assume a `clientId` that they are not assigned in their Ably-compatible token. They are unable to masquerade as another `clientId`.

## ClientId immutability <a id="immutability"/>

A connection's `clientId`, once set, is immutable. You cannot change a `clientId` after it has been established for a connection.

### Late initialization

It is possible to have late initialization of `clientId` in certain scenarios:

* AuthCallback discovery: When using `authCallback`, the `clientId` may only become known when the first authCallback completes and returns a token with a `clientId`.
* Opaque token processing: When the library receives an opaque token string, it only learns the `clientId` when it receives a response from the server that has processed the token.

In both cases, the immutability requirement is satisfied because the `clientId` gets set as part of the client's first interaction with the server. Once this initial authentication is complete, the `clientId` cannot be changed for that connection.

## Assign a clientId <a id="assign"/>

There are three different ways a client can be identified with using a `clientId`:
Expand Down
70 changes: 69 additions & 1 deletion src/pages/docs/auth/token.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,35 @@ One of the important benefits of using an Ably SDK is that the automatic refresh

To use automatic refresh of tokens, provide either an `authUrl` or an `authCallback`. When the token is near to expiry the `authUrl` or `authCallback` is invoked and a new token is automatically requested.

### Automatic renewal timing

The Ably SDK will automatically renew the authentication token when it is within 30 seconds of expiry to ensure no loss of service. This automatic renewal process ensures that connections remain active without interruption due to token expiration.

### Token authentication workflow

Understanding how token authentication works helps clarify why automatic renewal is essential:

1. Your server uses the Ably API key to request a 'Token Request' object from Ably.
2. Your client uses this 'Token Request' object to request the actual token from the Ably server every time it needs to authenticate.
3. These tokens are short-lived and expire after a certain period of time.
4. The client SDK automatically requests a new token just before the previous one expires, ensuring the connection never drops due to authentication failure.

Using an `authUrl` or `authCallback` ensures your client automatically requests a new token when needed, making the authentication process seamless and preventing service interruptions.

An `authURL` is recommended for use with web-based clients as they can easily utilize cookies and other web-only features. For non-web clients, `authCallback` is the recommended strategy.

### Token TTL limits

Ably enforces maximum TTL (time-to-live) limits on different types of tokens:

- Access tokens: Maximum TTL of 24 hours.
- Device tokens (for push notifications): Maximum TTL of 5 years.
- Revocable tokens: Maximum TTL of 1 hour (when [token revocation](/docs/auth/revocation#revocable-tokens) is enabled).

<Aside data-type="important">
Attempting to create a token with a TTL that exceeds these limits will result in an error code [40003](/docs/platform/errors/codes#40003).
</Aside>

### authUrl <a id="auth-url"/>

You can specify an `authUrl` when you create the Ably client. For example:
Expand Down Expand Up @@ -1004,7 +1031,7 @@ signature := base64.RawURLEncoding.EncodeToString(h.Sum(nil))
jwt := base64Header + "." + base64Claims + "." + signature
log.Println("JWT:", jwt)

// Send JWT to client (for demonstration, we print it here)
// Send JWT to client (for demonstration, print it here)
```

```flutter
Expand Down Expand Up @@ -1041,6 +1068,47 @@ final ablyJwt = "$base64Header.$base64Claims.$signature";
```
</Code>

## Dynamic channel access control <a id="dynamic-access"/>

Token authentication allows you to dynamically change a client's channel access permissions without disconnecting. Use the [`authorize()`](/docs/api/realtime-sdk/authentication#authorize) method to re-authenticate with updated [capabilities](/docs/auth/capabilities).

When you call `client.auth.authorize()`:

1. The client obtains a new token with different capabilities from your authentication server.
2. The new token is sent to Ably using the existing realtime connection.
3. The updated permissions are automatically applied without disconnecting.

### Use cases

You can trigger re-authentication in response to:
- Detect error code [40160](/docs/platform/errors/codes#40160) when a client attempts to attach to a channel.
- Instruct clients to re-authenticate via Ably channels or other communication methods.

The following example shows how to re-authenticate with updated capabilities:

<Code>
```javascript
// Re-authenticate to get new capabilities
try {
const newTokenDetails = await client.auth.authorize({
clientId: 'user123',
// Your auth server will return a token with updated capabilities
});
console.log('Successfully updated permissions');
} catch (error) {
console.error('Failed to re-authenticate:', error);
}
```
</Code>

For security purposes, handle non-compliant clients by:
- Set shorter token TTL expiry times to force frequent re-authentication (minimum 10 minutes recommended).
- Use the [token revocation API](/docs/auth/revocation) to immediately invalidate tokens.

<Aside data-type="important">
The `authorize()` method maintains the existing connection while updating permissions, making it ideal for real-time applications where connection continuity is important.
</Aside>

## When to use token auth <a id="when"/>

Ably recommends that token authentication is used client-side for the following reasons:
Expand Down
4 changes: 2 additions & 2 deletions src/pages/docs/channels/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ Channels are identified by their unique name. The following restrictions apply t
* They can't be empty
* They can't contain newline characters

While Ably doesn't limit the length of channel names, we recommend you keep them under 2048 characters, since some older browsers have trouble with long URLs.
While Ably doesn't limit the length of channel names, keeping them under 2048 characters is recommended, since some older browsers have trouble with long URLs.

Use the [`get()`](/docs/api/realtime-sdk/channels#get) method to create or retrieve a channel instance:

Expand Down Expand Up @@ -191,7 +191,7 @@ The channel rules related to security and client identity are:
| Rule | Description |
|------|-------------|
| Identified | If enabled, clients will not be permitted to use (including to attach, publish, or subscribe) matching channels unless they are [identified](/docs/auth/identified-clients) (they have an assigned client ID). Anonymous clients are not permitted to join these channels. Find out more about [authenticated and identified clients](/docs/auth/identified-clients). |
| TLS only | If enabled, only clients who have connected to Ably over TLS will be allowed to use matching channels. By default all of Ably's client libraries use TLS when communicating with Ably over REST or when using our Realtime transports such as Websockets. |
| TLS only | If enabled, only clients who have connected to Ably over TLS will be allowed to use matching channels. By default all of Ably's client libraries use TLS when communicating with Ably over REST or when using Realtime transports such as Websockets. |

The channel rules related to enabling features are:

Expand Down
57 changes: 56 additions & 1 deletion src/pages/docs/connect/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ It isn't possible to share a connection between browser tabs. This is because br

A connection ID is a unique identifier given to a connection, allowing for identifying and specifying particular connections.

An active connection ID is guaranteed to be unique in the Ably system whilst it is active, i.e. no other connection will share that connection ID. However, Ably reserves the right to generate a new connection ID later that may be the same as a previously discarded connection ID (once the connection is closed). Therefore we advise customers to not use the connection ID as a perpetual unique identifier as it is possible that a connection ID may be used many times.
An active connection ID is guaranteed to be unique in the Ably system whilst it is active, i.e. no other connection will share that connection ID. However, Ably reserves the right to generate a new connection ID later that may be the same as a previously discarded connection ID (once the connection is closed). Therefore customers are advised to not use the connection ID as a perpetual unique identifier as it is possible that a connection ID may be used many times.

### Connection metachannels <a id="metachannels"/>

Expand Down Expand Up @@ -200,6 +200,61 @@ AblyRealtime ably = new AblyRealtime(options);
```
</Code>

<If lang="javascript,nodejs">
## Browser page unload behavior <a id="page-unload"/>
In browser environments, ably-js automatically handles page unload events to ensure connections are properly closed when users navigate away or close pages.
### Default `beforeunload` behavior
By default, the Ably Pub/Sub JavaScript SDK adds a listener for the `beforeunload` event to cleanly close connections before a page is closed. This provides orderly behavior where:
* Connections are seen as having closed immediately by Ably servers.
* Presence members associated with the connection are seen by all users as having left immediately.

If a connection to Ably is not explicitly closed when there is a page unload event, then the connection state is preserved by Ably for 2 minutes. Preserving connection state for 2 minutes when there is an unexpectedly dropped connection provides the opportunity for the client to reconnect and resume the connection without losing any messages.

### Reliability considerations
The `beforeunload` event can be unreliable and is not guaranteed to fire under certain circumstances:
* The event may fire but the page is subsequently not disposed of (navigation can be cancelled).
* The handler in ably-js that closes a connection on a `beforeunload` event is hazardous unless the application developer is certain that there is no case where `beforeunload` fires, but the page is subsequently not unloaded.
* Recent releases of Chrome (version 108+) have introduced a Memory Saver feature that can cause pages to be discarded without firing `beforeunload` events.

### Chrome Memory Saver impact
Chrome's Memory Saver feature assists with controlling the browser's memory footprint by discarding inactive tabs. This significantly increases the frequency of pages being discarded, which:
* Causes JavaScript execution to stop without opportunity to intercept the event.
* Prevents connections from closing immediately since `beforeunload` doesn't fire.
* Results in longer delays before Ably recognizes the connection has closed.
* Affects presence members leaving immediately.

### Managing connection lifecycle
To ensure predictable connection closure behavior, consider these options:

Set `closeOnUnload:false` in [`ClientOptions`](/docs/api/realtime-sdk#client-options) when initializing the library:
<Code>
```realtime_javascript
const ably = new Ably.Realtime({
key: 'your-api-key',
closeOnUnload: false
});
```
```realtime_nodejs
const ably = new Ably.Realtime({
key: 'your-api-key',
closeOnUnload: false
});
```
</Code>
Manage connection lifecycle explicitly by calling [`close()`](/docs/api/realtime-sdk/connection#close) on the Ably realtime instance when it's no longer needed:
<Code>
```realtime_javascript
// When your application determines the connection should close
ably.close();
```
```realtime_nodejs
// When your application determines the connection should close
ably.close();
```
</Code>
Disable Chrome Memory Saver globally or on a site-by-site basis in browser settings if the feature is impacting your application's behavior.
</If>

## Close a connection <a id="close"/>

A connection to Ably should be closed once it is no longer needed. Note that there is a 2 minute delay before a connection is closed, if the [`close()`](/docs/api/realtime-sdk/connection#close) method hasn't been explicitly called. This is important to consider in relation to the number of [concurrent connections](/docs/platform/pricing/limits#connection) to your account.
Expand Down
Loading