Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
45d2691
my accounts and/or apps?
franrob-projects Sep 24, 2025
4e7fd64
What is the difference between 'failed' and 'refused' message statist…
franrob-projects Sep 24, 2025
ae4bc22
How do I access my app dashboard if I am a Heroku add-on user?
franrob-projects Sep 24, 2025
3d40cac
How is the 'peakRates' account stat defined?
franrob-projects Sep 24, 2025
9ecb206
What stats are available on my account and apps?
franrob-projects Sep 24, 2025
0757991
What is the relationship between Accounts and Apps
franrob-projects Sep 24, 2025
cbf6ebf
I purchased Ably through the AWS Marketplace but I am experiencing is…
franrob-projects Sep 24, 2025
e7b18cf
How do I delete an app?
franrob-projects Sep 24, 2025
15882d2
How can I restrict connections or requests by origin or IP?
franrob-projects Sep 24, 2025
815afad
Is it possible to restrict which channels or permissions an API key has?
franrob-projects Sep 25, 2025
461859a
Can I see which other users have access to my account?
franrob-projects Sep 25, 2025
8dce0a7
Can I force all account users to authenticate with SSO?
franrob-projects Sep 25, 2025
b177c71
How do I change my username or email?
franrob-projects Sep 25, 2025
a3a2f33
How do I verify my account via email?
franrob-projects Sep 25, 2025
26af5b6
How do I find out who the account owner is on my account?
franrob-projects Sep 25, 2025
0a1b6c9
How can I manage my email preferences for marketing, product and
franrob-projects Sep 25, 2025
6a34e10
Can I change my Ably account owner?
franrob-projects Sep 25, 2025
a1a1ce5
Why is the Realtime SDK always establishing Comet connections for lon…
franrob-projects Sep 25, 2025
a1977e6
Which transports are supported?
franrob-projects Sep 25, 2025
f63712b
Which TLS Version does the ably-js library use?
franrob-projects Sep 25, 2025
6958f11
Do you support multiplexing and channel groups?
franrob-projects Sep 25, 2025
1b7c7e8
If I need to whitelist Ably's servers from a firewall, which ports, I…
franrob-projects Sep 25, 2025
20766a0
Authenticated and identified clients
franrob-projects Sep 25, 2025
954546f
Are messages sent to and received from Ably securely using TLS?
franrob-projects Sep 25, 2025
ff8b914
How can you restrict which channels a client can access?
franrob-projects Sep 26, 2025
2b2aa91
When I change a key's capabilities in the dashboard, will existing co…
franrob-projects Sep 26, 2025
cef928f
Recommendations for incrementally authorising new capabilities
franrob-projects Sep 26, 2025
987548e
Is it secure to send the access_token as part of the websocket url qu…
franrob-projects Sep 26, 2025
952331a
Cross-platform symmetric encryption offered by the libraries
franrob-projects Sep 26, 2025
ba34624
How do I report a security or privacy vulnerability on Ably
franrob-projects Sep 26, 2025
1016538
Transport Layer Security (TLS) Version Support
franrob-projects Sep 26, 2025
1a78ede
Do you support MQTT? Are you protocol agnostic?
franrob-projects Sep 26, 2025
00a94b6
What are Ably protocol adapters and how do they work?
franrob-projects Sep 26, 2025
b36cb10
Where are Ably's servers and datacenters located around the world?
franrob-projects Sep 26, 2025
176ab35
Why does Ably have concurrent channel limits?
franrob-projects Sep 26, 2025
3a65d72
How do I avoid hitting the Max Channel Message Rate Limit by sharding…
franrob-projects Sep 26, 2025
f998268
Tidy up commit
franrob-projects Sep 30, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion content/partials/types/_client_options.textile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ h4.

<%= partial partial_version('shared/_token_auth_methods') %>

- <span lang="default">tls</span><span lang="csharp,go">Tls</span><span lang="ruby">:tls</span> := _true_ A boolean value, indicating whether or not a TLS ("SSL") secure connection should be used. An insecure connection cannot be used with Basic authentication as it would lead to a possible compromise of the private API key while in transit. "Find out more about TLS":https://faqs.ably.com/are-messages-sent-to-and-received-from-ably-securely-using-tls<br>__Type: @Boolean@__
- <span lang="default">tls</span><span lang="csharp,go">Tls</span><span lang="ruby">:tls</span> := _true_ A boolean value, indicating whether or not a TLS ("SSL") secure connection should be used. An insecure connection cannot be used with Basic authentication as it would lead to a possible compromise of the private API key while in transit. <span lang="javascript">The JavaScript library uses the TLS version supported by the browser environment.</span><span lang="nodejs">In Node.js, the TLS version is determined by the Node.js runtime version.</span> "Find out more about TLS":/docs/channels/options/encryption#tls<br>__Type: @Boolean@__

- <span lang="default">clientId</span><span lang="csharp,go">ClientId</span><span lang="python">client_id</span><span lang="ruby">:client_id</span> := A client ID, used for identifying this client when publishing messages or for presence purposes. The <span lang="default">@clientId@</span><span lang="ruby,python">@client_id@</span><span lang="csharp,go">@ClientId@</span> can be any non-empty string. This option is primarily intended to be used in situations where the library is instantiated with a key; note that a <span lang="default">@clientId@</span><span lang="ruby,python">@client_id@</span><span lang="csharp,go">@ClientId@</span> may also be implicit in a token used to instantiate the library; an error will be raised if a <span lang="default">@clientId@</span><span lang="ruby,python">@client_id@</span> specified here conflicts with the <span lang="default">@clientId@</span><span lang="ruby,python">@client_id@</span><span lang="csharp,go">@ClientId@</span> implicit in the token. "Find out more about client identities":/docs/auth/identified-clients<br>__Type: @String@__

Expand Down
12 changes: 11 additions & 1 deletion src/pages/docs/auth/capabilities.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,17 @@ API keys and Ably-compatible tokens, have a set of capabilities assigned to them

API keys are long-lived, secret and typically not shared with clients. API key capabilities are configured using the [dashboard](https://ably.com/dashboard), or using the [Control API](/docs/platform/account/control-api).

Ably-compatible tokens are designed to be shared with untrusted clients, are short-lived, and can be configured and issued programmatically. See [selecting an authentication mechanism](/docs/auth#selecting-auth) to understand why token authentication is the preferred option in most scenarios.
Ably-compatible tokens are designed to be shared with untrusted clients, are short-lived, and can be configured and issued programmatically. For restricting client access to channels, tokens provide far more flexibility and security than API key capabilities. See [selecting an authentication mechanism](/docs/auth#selecting-auth) to understand why token authentication is the preferred option in most scenarios.

### Capability changes and existing connections

<Aside data-type='important'>
When you change a key's capabilities in the dashboard, existing connections using that key do **not** receive the updated capabilities immediately. Connections must be closed and re-opened to pick up the new capabilities.
</Aside>

Once created, it's best to think of keys and tokens as being immutable. To modify the permissions granted to existing connections, the recommended approach is to use [token authentication](/docs/auth/token) and issue the client a new token with the updated permissions you want them to have.

The one exception is if a key is revoked entirely, in which case all connections using that key (or a token derived from that key) will be forcibly terminated. See [token revocation](/docs/auth/revocation) for more information.

## Resource names and wildcards <a id="wildcards"/>

Expand Down
16 changes: 16 additions & 0 deletions src/pages/docs/auth/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,22 @@ redirect_from:

Before a client or server can issue requests to Ably, such as subscribe to channels, or publish messages, it must authenticate with Ably. Authentication requires an Ably API key.

## Authentication terminology <a id="terminology"/>

The following terminology helps explain authentication, authorization, and identification in the context of the Ably service:

"Authentication" is the process of deciding, based on the presented credentials, whether or not an entity may interact with the Ably service. The credentials may be presented explicitly using [Basic Authentication](/docs/auth/basic) or [Token Authentication](/docs/auth/token), or in some cases the entity authenticating may prove possession of the credentials with a signed Token Request that is subsequently used to generate a valid token to be used for Token Authentication. When authenticating with Ably, the credentials are either an API key or an auth token.

"Authenticated client" is a client of the Ably service that has been successfully authenticated.

"Authorization" is the process of deciding whether or not a given entity (usually authenticated) is allowed to perform a given operation. In Ably, authorization for most operations is based on the [capabilities](/docs/auth/capabilities) associated with the key or token that was used to authenticate a client.

"Identified client" is an authenticated client with a specific claimed client identity, or `clientId`, whose credentials are verified as confirming that identity. See the [identified clients](/docs/auth/identified-clients) documentation for more information.

<Aside data-type='note'>
Channels can be configured to only allow [identified clients](/docs/auth/identified-clients). Learn more about [channel rules](/docs/channels#rules).
</Aside>

## Ably API keys <a id="api-keys"/>

Every Ably app can have one or more API keys associated with it in order to authenticate directly with Ably, or to issue tokens with. API keys can be created with different [capabilities](/docs/auth/capabilities) and any tokens issued using that API key can only permit a subset of those capabilities.
Expand Down
137 changes: 134 additions & 3 deletions src/pages/docs/auth/token.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,29 @@ Token authentication uses a trusted device with an [API key](/docs/auth#api-key)

Token authentication is the recommended authentication method to use client-side as it provides more fine-grained access control and limits the risk of credentials being exposed.

## Access restrictions <a id="restrictions"/>

### Token-based client validation

Token authentication enables you to validate client characteristics (such as origin, IP address, cookies, or any other client features) in your authentication server before issuing tokens. This provides flexible access control as you can implement any validation logic in your auth server as part of the token issuance process.

### API key restrictions

For cases where token authentication is impractical, Ably can add origin or IP address restrictions directly to API keys. However, this approach has significant limitations:

- Less flexible than token authentication.
- Manual intervention required to modify restrictions.
- Enterprise support packages only: contact [Ably support](https://ably.com/support) if interested.
- Not a security boundary: origin headers can be easily spoofed, especially outside browser contexts.
- Permissive fallback: requests with no origin header are allowed when origin restrictions are set.

For maximum security and flexibility, token authentication with server-side validation is the recommended approach.

Any of the following cause an SDK to use token authentication:

* An [`authUrl`](/docs/api/realtime-sdk/types#client-options) or [`authCallback`](/docs/api/realtime-sdk/types#client-options) is provided that returns an Ably-compatible token or an Ably [`TokenRequest`](/docs/api/realtime-sdk/types#token-request)
* [`useTokenAuth`](/docs/api/realtime-sdk/types#client-options) is true
* A [`token`](/docs/api/realtime-sdk/types#client-options) or [`tokenDetails`](/docs/api/realtime-sdk/types#client-options) property is provided
* An [`authUrl`](/docs/api/realtime-sdk/types#client-options) or [`authCallback`](/docs/api/realtime-sdk/types#client-options) is provided that returns an Ably-compatible token or an Ably [`TokenRequest`](/docs/api/realtime-sdk/types#token-request).
* [`useTokenAuth`](/docs/api/realtime-sdk/types#client-options) is true.
* A [`token`](/docs/api/realtime-sdk/types#client-options) or [`tokenDetails`](/docs/api/realtime-sdk/types#client-options) property is provided.

Providing a literal `token` or `tokenDetails` is typically used for testing: since tokens are short-lived, in production you typically want to use an authentication method that allows the client library to renew the token automatically before the current token expires.

Expand Down Expand Up @@ -1054,3 +1072,116 @@ When selecting an Ably SDK for implementing token authentication with Ably, you

As basic authentication is primarily designed for authenticating a secure server, in this situation, and assuming the server is only used for authentication, it is more efficient to use the REST interface, as the overhead associated with maintaining a realtime connection, is not required to issue tokens.
</Aside>

## Incremental authorization and reauth <a id="incremental-auth"/>

Ably's authentication uses a system of immutable tokens. Once created, tokens have a fixed set of [capabilities](/docs/auth/capabilities) that cannot be modified. However, there are scenarios where clients may need additional capabilities after their initial connection.

### Reauthorization process

When a client needs new capabilities, it can reauthorize by obtaining a new token from your auth server and calling [`auth.authorize()`](/docs/api/realtime-sdk/authentication#authorize). This upgrades the connection to use the new token without disrupting the existing connection or requiring reconnection.

### Reauthorization strategies

Choose the strategy that best fits your application architecture:

#### Server-determined capabilities

Best for applications with session management where the server maintains complete client state.

Your auth server tracks the canonical list of capabilities each client should have. When the client requests a new token, the server generates it with the complete capability set. This is the most secure approach as the server is the single source of truth.

#### Client-requested capabilities

Best for applications where clients need to request specific additional capabilities.

The client can request additional capabilities by including them in the token request:

- With `authUrl`: Use `authParams` or `authHeaders` in [client options](/docs/api/realtime-sdk/types#client-options) to send capability requests.
- With `authCallback`: Construct a custom request to your server with the needed capabilities.

Your server validates the request, updates its records of client capabilities, and issues a token with the complete capability set.

#### Client-managed capabilities

Best for stateless auth servers that cannot maintain client sessions.

The client maintains its own list of needed capabilities and sends the complete list to the server on each token request. The server validates each capability before issuing the token.

#### Signed capability storage

Best for stateless servers where re-validation of all capabilities is expensive.

Store client capabilities in a signed format (HMAC-signed cookie) to avoid trusting the client. When requesting new capabilities:

1. Server verifies the signature of existing capabilities.
2. Adds the new capability to the validated set.
3. Issues a token and updates the signed storage.

### Handling capability errors

When a client attempts an operation without proper capabilities, Ably returns an error with code `40160`. You can catch this error and trigger reauthorization:

```javascript
channel.attach((err) => {
if(err && err.code === 40160) {
console.log("Access denied - requesting new token with required capabilities");

// Update your capability requirements
channelsINeedAccessTo.push(channel.name);

// Reauthorize with new capabilities
realtime.auth.authorize((authErr) => {
if(!authErr) {
// Retry the original operation
channel.attach();
}
});
}
});
```

### Best practices

- **Server validation**: Always validate that clients should have access to requested capabilities
- **Minimal privileges**: Issue tokens with only the capabilities clients actually need
- **Token expiration**: Use appropriate token TTLs to balance security and performance
- **Error handling**: Implement robust error handling for capability-related failures
- **State management**: Choose the capability management strategy that fits your application's architecture

## WebSocket security considerations <a id="websocket-security"/>

When using tokens with WebSocket connections, developers often have concerns about including access tokens in WebSocket connection URLs as query parameters.

### Token placement security

From a security perspective, the location where an access token is stored (URL query parameters, headers, or message content) provides equivalent protection when connections use TLS:

- All connection data, including URLs and query parameters, are encrypted in transit.
- An attacker with access to inspect traffic can access tokens regardless of their location.
- TLS tunnels prevent proxies from accessing URL contents.

### Historical security concerns

Traditional concerns about credentials in query parameters arose from non-TLS environments and don't apply to modern WebSocket implementations:

Addressed concerns:
- Proxies cannot access URLs when using TLS tunnels.
- Browsers don't maintain history for WebSocket connections made by pages.
- TLS prevents intermediate systems from logging connection URLs.

Modern context:
- Most OAuth flows use `access_token` query parameters as standard practice.
- WebSocket connections default to TLS encryption.
- Client WebSocket implementations often don't support custom headers, making query parameters the practical choice.

### Recommendations

- Always establish WebSocket connections over TLS (WSS protocol).
- Use tokens with appropriate expiration times.
- Implement automatic token refresh for long-lived connections.
- Log and monitor token usage patterns for anomalies.

<Aside data-type='note'>
The security of your WebSocket authentication depends primarily on using TLS encryption and proper token management practices, rather than the specific method of token transmission.
</Aside>
12 changes: 12 additions & 0 deletions src/pages/docs/channels/index.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -217,3 +217,15 @@ Channel [history](/docs/storage-history/history) enables clients to retrieve mes
## Presence <a id="presence"/>

The [presence](/docs/presence-occupancy/presence) feature enables clients to be aware of other clients that are 'present' on the channel. Client status is updated as they enter or leave the presence set. Clients can also provide an optional payload describing their status or attributes, and trigger an update event at any time.

## Channel groups <a id="channel-groups"/>

Ably does not support channel groups, a concept used by some other providers where channels are placed into groups to work around limitations in dynamically subscribing or unsubscribing from channels.

**Why Ably doesn't need channel groups:**

* With Ably client libraries, you can add or remove subscriptions to channels dynamically at any tie.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo?

With Ably client libraries, you can add or remove subscriptions to channels dynamically at any tie.

* All channels operate over a single efficient connection.
* Channel namespaces already provide grouping functionality for configuration purposes.

Instead of channel groups, simply subscribe to the specific channels your client needs access to. The efficient multiplexing ensures optimal performance regardless of the number of channels.
Loading