Skip to content

Conversation

@umair-ably
Copy link
Contributor

Description

Comprehensive overhaul of authentication documentation to help developers choose the right auth method and implement it securely.

Key additions:

  • 4 new guides: JWT integration (Auth0/Firebase/Cognito), authentication quick reference, and dedicated Chat/Spaces auth guides
  • Token mechanism comparison: New "Choosing a token mechanism" section in /docs/auth/token comparing TokenRequest vs Ably JWT vs Embedded JWT with decision criteria and architectural scenarios
  • Security-first messaging: Added explicit warnings about API key exposure to all getting-started guides (React, Swift, Android, etc.)
  • MQTT JWT auth: New section documenting JWT authentication for IoT/embedded devices

Changes across 46 files:

  • auth/token.mdx: +400 lines covering token selection, JWT-only features, and scenarios (standard apps, existing JWT infra, IoT, serverless, multi-tenant SaaS, rate limiting)
  • auth/capabilities.mdx: Added callouts clarifying JWT-only features (channel claims, rate limits)
  • chat/setup.mdx, spaces/setup.mdx: Restructured to lead with token auth, added JWT alternative
  • All getting-started guides: Replaced ambiguous "use token auth in production" with explicit security warnings
  • Navigation: Added new pages to Chat, Spaces, and Pub/Sub nav trees

Why this matters:

  • Users frequently misunderstand when to use API keys vs tokens
  • JWT integration with existing identity providers (Auth0, Firebase, Cognito) was undocumented
  • No clear guidance existed on JWT-only features like channel claims and rate limits
  • Getting-started guides implied API keys were acceptable for development without emphasizing the security boundary

Checklist

@coderabbitai
Copy link

coderabbitai bot commented Jan 7, 2026

Important

Review skipped

Auto reviews are disabled on this repository.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@umair-ably umair-ably added the review-app Create a Heroku review app label Jan 7, 2026
@ably-ci ably-ci temporarily deployed to ably-docs-authchanges-py2loc0j January 7, 2026 17:48 Inactive
Copy link
Member

@paddybyers paddybyers left a comment

Choose a reason for hiding this comment

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

I've commented on much of this but stopped around half way through. I think it needs significant revision to make JWT the primary recommended route. The narrative and examples all need updating to reflect this.

A lot of this is slop - it's been AI-generated and not critically reviewed.

```javascript
// ALWAYS use token authentication in browsers
const realtime = new Ably.Realtime({
authUrl: '/api/ably-token',
Copy link
Member

Choose a reason for hiding this comment

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

Why are we suggesting authURL instead of callback here? Does it not need at least some comment?

## Server auth endpoint template
Your server needs an endpoint that creates tokens. Here's a minimal example:
Copy link
Member

Choose a reason for hiding this comment

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

Why is this using native tokens, instead of generating a JWT?

```
</Code>
## Security comparison
Copy link
Member

Choose a reason for hiding this comment

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

I'm not convinced this section adds anything. It feels like slop.

Copy link
Member

Choose a reason for hiding this comment

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

really a duplciate of https://ably-docs-authchanges-py2loc0j.herokuapp.com/docs/auth#selecting-auth. I do thinkg repetition is good at times, but why here?

- [Token authentication reference](/docs/auth/token) - Full token auth documentation
- [Capabilities](/docs/auth/capabilities) - Fine-grained permission control
## Troubleshooting
Copy link
Member

Choose a reason for hiding this comment

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

These are not the only things that could go wrong, or even the most likely things that could go wrong.

Error 40103: Token expired

Not according to https://github.com/ably/ably-common/blob/main/protocol/errors.json#L40

If we're going to retain this section we should also refer to:
40160: incorrect capabilities
80019: error in auth callback/url
40171: no means to renew token

Perhaps we should defer adding this section until we've got the more thorough error code documentation landed?

Copy link
Member

Choose a reason for hiding this comment

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

Why do we need troubleshooting at all? We have error codes and paths. Do we think people are going to read this and pre-empty troubles?


### TokenRequest <a id="choosing-tokenrequest"/>

**Best for:** Standard web and mobile applications using Ably SDKs.
Copy link
Member

Choose a reason for hiding this comment

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

I don't agree with this. We recommend JWT in all circumstances that they can be used. There are only two situations where you would use native tokens:

  • where the capabilities list is so large that a literal token is unworkable;
  • where the capabilities or clientId are sensitive in some way, and there is a desired to keep them confidential, even if inspecting the token.

Of these, I'm not sure we should even mention the second one because it's such an unusual case.

Occupancy generates messages on any client entering/leaving a room, and so increases the number of billable messages sent in a room - as such, it is disabled by default and needs to be [enabled](/docs/chat/rooms#create) when creating or retrieving a room.
</Aside>

<Aside data-type='note'>
Copy link
Member

Choose a reason for hiding this comment

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

This is irrelevant. I suggest removing it.

The presence feature of a chat room enables online users to advertise to others that they are online. Use this feature to build online status indicators to display who is online in a chat room. Users can also share additional information such as avatar URLs or custom statuses.

<Aside data-type='note'>
**Authentication required:** Presence requires an authenticated client with a `clientId`. Clients without a `clientId` cannot enter the presence set. Use [token authentication](/docs/auth/token) with server-assigned client IDs for production applications. See the [Chat setup guide](/docs/chat/setup#authentication) for examples.
Copy link
Member

Choose a reason for hiding this comment

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

This should refer to identified clients.


Room reactions are ephemeral and not stored or aggregated by Ably. The intention being that they show the overall sentiment of a room at a point in time.

<Aside data-type='note'>
Copy link
Member

Choose a reason for hiding this comment

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

This is incorrect advice. It should state instead that a client needs to be identified in order to use certain reaction types. It does not imply the use of token auth.

Typing indicators enable you to display which users are currently writing a message in a room. This feature can be used to display a message such as *Sandi is typing...*, or when a certain threshold is reached you could instead display *Multiple people are typing...* or *12 people are typing...*. Typing events are emitted whenever a user starts or stops typing.

<Aside data-type='note'>
**Authentication required:** Typing indicators display the `clientId` of users who are typing. Use [token authentication](/docs/auth/token) to ensure these identities are trustworthy. See the [Chat setup guide](/docs/chat/setup#authentication) for examples.
Copy link
Member

Choose a reason for hiding this comment

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

I don't understand why this comment is here. Doesn't the chat SDK ensure that a client is always identified?

Copy link
Member

Choose a reason for hiding this comment

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

Yes it does, this is needless information as they cannot connect without a clientId


Your server needs an endpoint that:
1. Verifies the user is authenticated (check session, JWT, etc.)
2. Creates an Ably TokenRequest with the user's identity
Copy link
Member

Choose a reason for hiding this comment

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

Again, we should be recommending JWT auth.

Copy link
Member

@mattheworiordan mattheworiordan left a comment

Choose a reason for hiding this comment

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

Thanks for submitting. Good to see you take a stab at dealing with the LLM auth issues, but I think this PR needs a lot more human review by yourself before it's sent for others to review. Lots of obvious problems as it appears to have been pumped out directly from an LLM, which is great to move quickly, but thiks is our docs, and is representative of whether we care to customers.


## Approach 1: Separate Ably JWT <a id="separate-jwt"/>

Your existing auth flow validates the user, then you create an Ably JWT using any JWT library. No Ably SDK is required on your server.
Copy link
Member

Choose a reason for hiding this comment

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

I am not sure this is what we'd recommend, always sending both tokens instead of just the one you need? Why would a single endpoint be used for Ably and app auth, when both only need one of the two JWTs?

authCallback: async (tokenParams, callback) => {
// On token refresh, fetch new Ably JWT
try {
const response = await fetch('/auth/ably-token', {
Copy link
Member

Choose a reason for hiding this comment

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

This URL doesn't match the server example you have above

// On token refresh, fetch new Ably JWT
try {
const response = await fetch('/auth/ably-token', {
headers: { 'Authorization': `Bearer ${appToken}` },
Copy link
Member

Choose a reason for hiding this comment

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

This approach is broken in that a new app token cannot be generated as it's cached at the time of login, instead of obtaining one at the time it's needed

'x-ably-token': ablyToken.token,
},
process.env.APP_JWT_SECRET,
{ expiresIn: '1h' } // Must not exceed Ably token expiry
Copy link
Member

Choose a reason for hiding this comment

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

If that's teh case, why are you not specifying a TTL when issuing the token?

```
</Code>

## Integrating with AWS Cognito <a id="cognito"/>
Copy link
Member

Choose a reason for hiding this comment

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

I am not sure we should be just listing out integrations with random providers like this. It doesn't really flow, at the start we're talking about issuing JWTs ,then we are showing random integrations where with this one we're just showing how to issue a token with Lambda, and then we move onto token renewal. It doesn' feel well thought through, why this order?

If your `authUrl` endpoint is slow or unreliable, tokens may expire before refresh completes. Ensure your auth endpoint responds quickly (under 5 seconds) and is highly available.
## Next steps
Copy link
Member

Choose a reason for hiding this comment

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

Why have you introduced Next Steps? We've not used this in the docs.

The Ably SDK automatically calls your `authCallback` before the current token expires, ensuring seamless token rotation.
## Next steps
Copy link
Member

Choose a reason for hiding this comment

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

Why have you introduced Next Steps? We've not used this in the docs.

If your `authUrl` endpoint is slow or unreliable, tokens may expire before refresh completes. Ensure your auth endpoint responds quickly (under 5 seconds) and is highly available.
## Next steps
Copy link
Member

Choose a reason for hiding this comment

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

Why have you introduced Next Steps? We've not used this in the docs.

Typing indicators enable you to display which users are currently writing a message in a room. This feature can be used to display a message such as *Sandi is typing...*, or when a certain threshold is reached you could instead display *Multiple people are typing...* or *12 people are typing...*. Typing events are emitted whenever a user starts or stops typing.

<Aside data-type='note'>
**Authentication required:** Typing indicators display the `clientId` of users who are typing. Use [token authentication](/docs/auth/token) to ensure these identities are trustworthy. See the [Chat setup guide](/docs/chat/setup#authentication) for examples.
Copy link
Member

Choose a reason for hiding this comment

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

Yes it does, this is needless information as they cannot connect without a clientId

Subscribe to the `space.members` namespace in order to keep your avatar stack updated in realtime.

<Aside data-type='note'>
**Authentication required:** This feature uses the client's `clientId` for identification. Use [token authentication](/docs/auth/token) with server-assigned client IDs to prevent identity spoofing. See the [Spaces setup guide](/docs/spaces/setup#authenticate) for examples.
Copy link
Member

Choose a reason for hiding this comment

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

This is not necessary. If this is needed, the problem of which auth mechanism t use is surely solved?

@umair-ably
Copy link
Contributor Author

Thanks both @mattheworiordan @paddybyers

I should've made it clear I had not yet reviewed the LLM output, so this at the very least should've been a draft only! I mostly put it up to get a gauge on the kind of content we think we were missing and the placement of it.

However, your comments have massively helped me in understanding the scope of what needs changing in our auth docs, as well as highlighting my limited understanding of exactly what we're trying to tell and recommend to our customers. I've got a session with Mark and Paddy shortly to understand exactly what our position is re: Auth with Ably, what we're trying to tell our customers, and some historical context of how auth has evolved to the point we seem to have deviations in our docs.

I'm trying to solely use LLMs for this, so again, some of these changes are likely subpar as I get a better understanding of the problem later today. For the time-being, I've gone back and forth with Claude to "resolve" (or at least have a stab at resolving) your current comments.

I would ignore this for now until I've had a chance to capture and implement the findings from our meeting later today - this is purely to move the needle and help my own understanding from what you've presented in the comments so far.

Comments on auth/quick-reference.mdx (12 comments)

Comment Resolved
paddybyers: Why authURL instead of callback? ✅ Added "authUrl vs authCallback" section explaining both
paddybyers: Why native tokens instead of JWT? ✅ Server examples now generate JWTs directly
paddybyers: Security comparison feels like slop ✅ Section removed
paddybyers: Troubleshooting section issues ✅ Section removed
mattheworiordan: Decision matrix unclear ✅ Removed, simplified to code examples
mattheworiordan: Duplicating overview page ✅ Simplified to quick reference focus
mattheworiordan: Server using Realtime not REST ✅ Now uses Ably.Rest server-side
mattheworiordan: getUserIdFromRequest odd name ✅ Now uses req.user?.id (auth middleware pattern)
All troubleshooting/product links comments ✅ These sections removed

Comments on auth/token.mdx (8 comments)

Comment Resolved
paddybyers: JWT should be primary, not TokenRequest ✅ "Ably JWT is recommended for most use cases"
paddybyers: Serverless in wrong section ✅ Moved to JWT section (stateless)
paddybyers: TokenRequest advantages become disadvantages ✅ Restructured with proper trade-offs
paddybyers: Too much repetition ✅ Cleaned up, table simplified
mattheworiordan: Table values questionable ✅ Table revised with clearer yes/no values

Comments on auth/jwt-integration.mdx (8 comments)

Comment Resolved
mattheworiordan: Sending both tokens wrong ✅ File simplified, single endpoint approach
mattheworiordan: URL mismatch ✅ Consistent /api/ably-jwt throughout
mattheworiordan: Token caching broken ✅ Now uses proper authCallback pattern
mattheworiordan: No TTL specified ✅ expiresIn: '1h' now included
mattheworiordan: Random provider list ✅ Provider integrations removed
mattheworiordan: getCurrentAppToken confusing ✅ Removed
mattheworiordan: "Next Steps" not used in docs ✅ Section removed

Comments on chat/authentication.mdx (12 comments)

Comment Resolved
paddybyers: Should recommend JWT ✅ Creates JWTs directly
mattheworiordan: authMethod/authHeaders inconsistent ✅ Examples now consistent using authCallback
mattheworiordan: Send/receive should be separate ✅ Capability table has separate rows
mattheworiordan: Missing annotations/mutations ✅ Table includes annotation-publish, etc.
mattheworiordan: Wrong namespace format ✅ Correct my-room::$chat format
mattheworiordan: "Next Steps" section ✅ Removed

Comments on Chat Room Features (6 comments)

File Comment Resolved
rooms/occupancy.mdx Auth callout irrelevant ✅ Removed
rooms/presence.mdx Should link to identified-clients ✅ Links to /docs/auth/identified-clients
rooms/reactions.mdx Should mention identified clients ✅ Now references identified clients
rooms/typing.mdx Unnecessary auth note ✅ Removed

Comments on chat/setup.mdx (1 comment)

Comment Resolved
Empty code blocks ✅ All code blocks now have content

Comments on spaces/authentication.mdx & spaces/avatar.mdx (2 comments)

Comment Resolved
"Next Steps" not used in docs ✅ Removed
Auth note unnecessary in avatar.mdx ✅ Removed

Key Changes Made

  1. JWT is now the recommended primary auth mechanism throughout all docs
  2. Removed unnecessary sections: Security comparison, Troubleshooting, Next Steps, Provider integrations
  3. Server examples use REST client instead of Realtime
  4. Consistent authCallback examples across all SDKs
  5. Accurate capability tables with separate permissions
  6. Proper identified client references in Chat features
  7. jwt-integration.mdx dramatically simplified from ~430 lines to ~89 lines
  8. Fixed empty code blocks in setup.mdx

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

review-app Create a Heroku review app

Development

Successfully merging this pull request may close these issues.

5 participants