Skip to content

[FTF-468] Several docs changes to highlight token auth over API key auth, as well as more info on using JWTs#3085

Open
umair-ably wants to merge 8 commits intomainfrom
authChanges
Open

[FTF-468] Several docs changes to highlight token auth over API key auth, as well as more info on using JWTs#3085
umair-ably wants to merge 8 commits intomainfrom
authChanges

Conversation

@umair-ably
Copy link
Contributor

@umair-ably umair-ably commented Jan 7, 2026

Description

  • Restructures auth documentation to recommend token authentication (specifically Ably JWT) as the default for client-side applications
  • Adds new dedicated authentication pages for Chat and Spaces products
  • Expands token auth documentation with a comparison table of token mechanisms and clearer guidance on choosing between Ably JWT, TokenRequest, and Embedded JWT
  • Updates auth landing page with a quick reference table and starter code example
  • Streamlines capabilities and identified-clients pages for clarity

Motivations/Objectives:

  • JWT Token Auth becomes the obvious and clear auth pattern for production code.
  • Customer's are easily able to navigate the docs site to find the appropriate auth info e.g. product specific auth guidance is nested in the product section. Auth is moved under platform. (Will be added in a later PR)

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.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch authChanges

Tip

Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs).
Share your feedback on Discord.


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?

@ably-ci ably-ci temporarily deployed to ably-docs-authchanges-py2loc0j January 8, 2026 12:31 Inactive
@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

@ably-ci ably-ci temporarily deployed to ably-docs-authchanges-py2loc0j January 13, 2026 08:13 Inactive
@umair-ably umair-ably marked this pull request as draft January 13, 2026 08:14
@ably-ci ably-ci temporarily deployed to ably-docs-authchanges-py2loc0j January 13, 2026 08:25 Inactive
@ably-ci ably-ci temporarily deployed to ably-docs-authchanges-py2loc0j January 13, 2026 09:40 Inactive
@ably-ci ably-ci temporarily deployed to ably-docs-authchanges-py2loc0j January 13, 2026 10:31 Inactive
@ably-ci ably-ci temporarily deployed to ably-docs-authchanges-py2loc0j January 14, 2026 09:23 Inactive
@umair-ably umair-ably marked this pull request as ready for review January 14, 2026 09:31
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.

This is really hard to review because it's dominated by changes to the path for the auth docs. Please at least make all of those changes in a separate commit (but I don't see why it's not a separate PR). Then the other material changes can be reviewed.

@umair-ably
Copy link
Contributor Author

This is really hard to review because it's dominated by changes to the path for the auth docs. Please at least make all of those changes in a separate commit (but I don't see why it's not a separate PR). Then the other material changes can be reviewed.

that's fair - the change was from our meeting in which we wanted auth docs under platform with shorter product auth guides in their respective sections. This then meant leaving the path as docs/auth or changing it to docs/platform/auth... I went with the latter purely because it matches the nav stack. I'll change it for the sake of this PR

@ably-ci ably-ci temporarily deployed to ably-docs-authchanges-py2loc0j January 14, 2026 11:01 Inactive
@umair-ably
Copy link
Contributor Author

@paddybyers I also unified the messaging we had when pointing people to the token auth docs... I'll revert this and do that as a separate PR.. just a moment

@ably-ci ably-ci temporarily deployed to ably-docs-authchanges-py2loc0j January 14, 2026 11:45 Inactive
@umair-ably
Copy link
Contributor Author

@mattheworiordan @paddybyers

Previous comments should be addressed.

There was a fair few more changes that I'll instead add in a subsequent PR (adding asides to current basic auth code examples which highlight using JWT token in prod, and redirects to ensure links point to the new auth docs location under platform)


### JWT Authentication <a id="jwt-auth"/>

<Aside data-type='note'>
Copy link
Contributor Author

Choose a reason for hiding this comment

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

remove this... duplicate

@ably-ci ably-ci temporarily deployed to ably-docs-authchanges-py2loc0j January 15, 2026 08:57 Inactive
@ably-ci ably-ci temporarily deployed to ably-docs-authchanges-py2loc0j January 15, 2026 09:02 Inactive
@umair-ably
Copy link
Contributor Author

@paddybyers

Undone all nav changes for this PR... All auth docs changes are now isolated to their original location (under pubsub) and new product specific auth pages e.g. Chat and Spaces.

Upcoming PR(s) will reintroduce:

  • Moving auth docs from pubsub to platform (and redirects where needed)
  • MQTT and SSE docs changes
  • Unifying and adding messaging around using JWT token auth where we have basic auth code examples

cc: @m-hulbert

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.

Please see the comments. I think this still needs some work.

Discussions relating to auth have lots of scope for ambiguity so please use precise language. Every word has one meaning, and every meaning has one word.

@m-hulbert I'll defer to you on whether or not the restructure makes sense wrt the nav.

Someone from the Chat team needs to review the chat parts - having the ::$chat directive in the capability expression I'm sure is wrong (@splindsay-92 )

Capabilities can be set when creating a token or token request, as shown in the following example:
#### Using JWT (recommended) <a id="jwt-capabilities"/>

Set capabilities in a JWT using the `x-ably-capability` claim. No Ably SDK is required—any JWT library will work:
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Set capabilities in a JWT using the `x-ably-capability` claim. No Ably SDK is requiredany JWT library will work:
Set capabilities in a JWT using the `x-ably-capability` claim. No Ably SDK is required - any JWT library will work:

Please no em-dashes

Copy link
Member

Choose a reason for hiding this comment

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

Maybe worth just adding
This example uses jsonwebtoken
?

capability := map[string][]string{
"*": {"*"},
}
If JWT is not suitable, use the Ably SDK to create a TokenRequest with capabilities:
Copy link
Member

Choose a reason for hiding this comment

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

This says nothing about why JWT might not be suitable


### Token capability determination <a id="capability-determination"/>

The capabilities for tokens are determined based on those of the issuing API key and those requested by the token.
Copy link
Member

Choose a reason for hiding this comment

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

I think this needs to be more explicit. The capabilities of the resulting token are the intersection of the request capabilities, and those of the issuing API key. (This is also true for JWT.)

The requestToken() request will fail if the intersection is empty - ie the token would have no rights.

This should also mention the gotcha: this intersection behaviour means that a call to requestToken() will succeed, but can fail to provide a token with all of the requested capabilities. If the capabilities of the issuing key are not known by the client, then a successful response to requestToken() should be followed by a check that all of the requested capabilities are present.

## Custom restrictions on channels <a id="custom-restrictions"/>

<Aside data-type='important'>
**JWT-only feature:** Channel-scoped user claims are only available when using [Ably JWT authentication](/docs/auth/token#choosing-jwt). They are not available with TokenRequest authentication. See [JWT-only features](/docs/auth/token#jwt-only-features) for a complete list of capabilities exclusive to JWT authentication.
Copy link
Member

Choose a reason for hiding this comment

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

@m-hulbert Are we happy that "TokenRequest authentication" is the appropriate name in these docs for the native token mechanism?

Copy link
Contributor

Choose a reason for hiding this comment

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

I think the high-level mechanism should be 'Ably Tokens' personally.


It is possible for JWTs to contain authenticated claims for users that can be used to allow or disallow certain interactions in your channels.

Messages can be annotated with trusted metadata copied from the client's authentication token by Ably servers. Clients are unable to directly publish messages with user claim metadata, and claims contained within the authentication token are signed to prevent tampering. Claims can be scoped to individual channels or to namespaces of [channels](/docs/channels). The most specific user claim will be added to the message as part of the `extras` object. Note that this does not apply to presence or metadata messages.
Copy link
Member

Choose a reason for hiding this comment

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

Note that this does not apply to presence

I thought we support that now - pls check

* Ably [TokenRequest](#token-request) is created by your servers and passed to clients.
* An [Ably Token](#ably-token) is issued by your servers and passed to clients.

Note that the machine on which you are running your auth server should have an accurate clock, as tokens and `TokenRequest` contain a timestamp. You can use an [NTP daemon](https://en.wikipedia.org/wiki/Ntpd), or if you are not able to control your server's clock, you can wish to use the `queryTime` [auth option](/docs/api/rest-sdk/types#auth-options).
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
Note that the machine on which you are running your auth server should have an accurate clock, as tokens and `TokenRequest` contain a timestamp. You can use an [NTP daemon](https://en.wikipedia.org/wiki/Ntpd), or if you are not able to control your server's clock, you can wish to use the `queryTime` [auth option](/docs/api/rest-sdk/types#auth-options).
Note that the machine on which you are running your auth server should have an accurate clock, as tokens and `TokenRequest` contain a timestamp and have limited validity. You can use an [NTP daemon](https://en.wikipedia.org/wiki/Ntpd), or if you are not able to control your server's clock, you can wish to use the `queryTime` [auth option](/docs/api/rest-sdk/types#auth-options).


### Multi-tenant SaaS with user roles <a id="scenario-multitenant"/>

**Recommendation: Ably JWT with channel claims**
Copy link
Member

Choose a reason for hiding this comment

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

Please do not use bold like this. Use a heading if appropriate, or just plain text.

I don't understand why these channel claims are relevant to this use-case - can you explain?

```
</Code>

Other clients can read these trusted claims from presence or message metadata.
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 relevant to a multi-tenanted system?

{
'x-ably-capability': JSON.stringify({
// Only allow access to a specific room
'your-room::$chat': ['publish', 'subscribe', 'presence', 'history'],
Copy link
Member

Choose a reason for hiding this comment

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

I think this is incorrect. A resource specifier in a capability expression will match on the channel name without the directive part.


<Aside data-type='important'>
The examples use basic authentication to demonstrate features for convenience. In your own applications, basic authentication should never be used on the client-side as it exposes your Ably API key. Instead, use token authentication.
**Security requirement:** Client-side applications must use [JWT token authentication](/docs/auth/token#choosing-jwt). Never expose your API key in client-side code.
Copy link
Member

Choose a reason for hiding this comment

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

Please don't use bold like this.
Please don't use the word "security" like this. There are words that mean the specific thing you're trying to say.

@m-hulbert m-hulbert temporarily deployed to ably-docs-authchanges-i9bbknme January 28, 2026 09:17 Inactive
Copy link
Contributor

@m-hulbert m-hulbert left a comment

Choose a reason for hiding this comment

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

Thanks Umair.

I can see this starting to take shape, but I think we need to make some larger changes, as we've made a long page even longer (and arguably more complicated) - with the actual code to get up and running 40% down the page.

I think we should split up the token authentication page into 3/4 separate ones;

  • Overview
    • Covers anything that is true for all forms of token authentication.
    • I think this needs to mention that authentication is handled by the Pub/Sub SDK and what that means for other products.
  • JWTs
    • Just info on JWTs with a mention at the top that it's recommended. authCallback used in examples in all languages - authUrl can be further down with associated examples, but most people will use the callback.
    • Note on when you'd use Ably native Tokens instead in the intro.
  • Ably Tokens
    • Note at the top that JWTs are recommended and you'd only use Ably Tokens in these circumstances.
    • All info on Ably Token mechanisms. (I'd also include a token embedded in a JWT on this page personally, but defer to @paddy on the popularity of that).
  • Token revocation
    • Makes sense to nest this if we create this section.

We've also added a lot of "JWT is recommended" in places, but I feel we should just stick to the points around length of the JWT and its publicly visible claims. If we create a token authentication overview, I feel all we need to state is 'use JWT authentication unless...". And then reiterate that at the top of the JWT and Ably Token pages.

Can we also ensure we have full coverage for all languages whilst we're updating this please?


## Token mechanism comparison <a id="comparison"/>

| Feature | Ably JWT (Recommended) | Embedded JWT | TokenRequest |
Copy link
Contributor

Choose a reason for hiding this comment

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

I feel this is sort of trying to justify the use of JWTs which I'm not sure is strictly necessary if we position it as the recommended approach. Would be curious on other opinions though.


| Feature | Ably JWT (Recommended) | Embedded JWT | TokenRequest |
|---------|:----------------------:|:------------:|:------------:|
| **Server SDK required** | No | Yes | Yes |
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure why some of these rows are bold and others aren't.

meta_description: "Configure authentication for Chat applications with the required capabilities."
---

This page covers Chat-specific capabilities and room scoping. For client setup and server implementation, see [SDK setup](/docs/chat/setup).
Copy link
Contributor

Choose a reason for hiding this comment

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

We don't tend to write 'this page covers'. This should dive straight into what Chat authentication is, and that it's handled by the Pub/Sub SDK.

We also spoke about this replacing the SDK setup page, so I don't think we should be updating that page, and adding this one as it's just splitting the info between two pages. Especially when this page (which should be the go-to for auth) is only showing JS examples.


Capabilities are permissions that control what operations a client can perform. When you create a token for a Chat user, you specify which capabilities they have. Each Chat feature requires specific capabilities:

| Feature | Required Capabilities |
Copy link
Contributor

Choose a reason for hiding this comment

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

We seem to have taken the table from the existing setup page and added more rows unnecessarily.

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

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

Choose a reason for hiding this comment

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

We should be using the variable for a demo key in all code examples please.


- **Token lifecycle**: Tokens expire and the SDK automatically refreshes them via your `authCallback` - see [Token authentication](/docs/auth/token)
- **Revoke access**: You can instantly revoke tokens for compromised or banned users - see [Token revocation](/docs/auth/revocation)
- **Dynamic permissions**: Users can get new capabilities by re-authenticating (e.g., when a moderator grants permissions) - see [Capabilities](/docs/auth/capabilities)
Copy link
Contributor

Choose a reason for hiding this comment

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

Can we ensure links are included inline rather than having 'see X' or 'read more' everywhere please.

@@ -0,0 +1,115 @@
---
title: Spaces authentication
Copy link
Contributor

Choose a reason for hiding this comment

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

I think most of my comments from chat are relevant here.


## Space-scoped capabilities

You can restrict tokens to specific spaces. Spaces uses multiple channels per space:
Copy link
Contributor

Choose a reason for hiding this comment

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

This is the first point we're mentioning that space is equivalent to a channel. Before now you have no idea or concept of their relationship.

## Space-scoped capabilities

You can restrict tokens to specific spaces. Spaces uses multiple channels per space:
- The main space channel (`your-space`) handles presence and member locations
Copy link
Contributor

Choose a reason for hiding this comment

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

IIRC the channel name is your-space::$space. I'm not 100% if spaces directives are handled in capabilities automatically the same way that chat ones are though.


Use `authCallback` to fetch JWTs from your auth server:

<Code>
Copy link
Contributor

Choose a reason for hiding this comment

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

Also needs React.

  - Adds full code examples to product-specific auth pages
  - Updates nav and cross-references to highlight token auth over API key auth
@GregHolmes GregHolmes removed the request for review from franrob-projects February 13, 2026 10:13
@m-hulbert m-hulbert temporarily deployed to ably-docs-authchanges-affotrbj February 18, 2026 08:11 Inactive
Copy link
Contributor

@m-hulbert m-hulbert left a comment

Choose a reason for hiding this comment

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

Thanks Umair - still a few things that don't quite match up throughout or are still stating incorrect behaviour.

I think to summarise:

  • Code should be available in all languages supported by that SDK client-side. Server-side should cover all popular choices here, but the key is to be consistent wherever we're providing code.
  • The Chat directive issue is still included here which I'm 99% sure is wrong.
  • There's some content being included in JWTs that is applicable to all auth types.
  • We have some odd duplication of tables and content that aren't quite the same, but should be centralised when helping someone choose the right auth mechanism.

The following terminology helps explain authentication, authorization, and identification in the context of the Ably service:
| Environment | Recommended Method | Details |
|-------------|-------------------|---------|
| **Client-side** (browsers, mobile apps) | [Token authentication](/docs/auth/token) | Your server creates Ably Tokens (JWT format recommended for most apps); clients use `authCallback` to fetch them |
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure 'Ably Tokens' is the correct term here to encompass JWT and what we're referring to as 'Ably Tokens'.


"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.
<Aside data-type='important'>
**Never use API keys in client-side code.** API keys don't expire. Once compromised, they grant indefinite access. Use [token authentication](/docs/auth/token) with tokens that can have narrowly-scoped capabilities, can be short-lived, and can be revoked.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
**Never use API keys in client-side code.** API keys don't expire. Once compromised, they grant indefinite access. Use [token authentication](/docs/auth/token) with tokens that can have narrowly-scoped capabilities, can be short-lived, and can be revoked.
**Never use API keys in client-side code.** API keys don't expire. Once compromised, they grant indefinite access. Use [token authentication](/docs/auth/token) with tokens that have narrowly-scoped capabilities, are short-lived, and can be revoked.

</Aside>

"Authenticated client" is a client of the Ably service that has been successfully authenticated.
### Quick start
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is a bit odd to have on the overview without any context. I think we've done enough to funnel people to JWTs without it.

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

- **Authentication**: The process of verifying credentials (API key or token) to allow interaction with Ably.
- **Authorization**: Determining what operations an authenticated client can perform, based on [capabilities](/docs/auth/capabilities).
Copy link
Contributor

Choose a reason for hiding this comment

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

We're listing 'authorization' here but then we never use that word again other than referring to the authorize method.

We've also got the obvious bolded list LLM approach here.

## 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.
Every Ably app can have one or more API keys associated with it. API keys authenticate directly with Ably or issue tokens. Keys can have different [capabilities](/docs/auth/capabilities), and tokens issued from a key can only have a subset of those capabilities.
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
Every Ably app can have one or more API keys associated with it. API keys authenticate directly with Ably or issue tokens. Keys can have different [capabilities](/docs/auth/capabilities), and tokens issued from a key can only have a subset of those capabilities.
Every Ably app can have one or more API keys associated with it. API keys authenticate directly with Ably or are used to issue tokens.
Keys can have different [capabilities](/docs/auth/capabilities), and tokens issued from a key can only request a subset of those capabilities.

```
</Code>

## Client examples
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the code might be better directly after 'authentication flow' maybe - WDYT?

## 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.
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the code sample needs to be directly below this point.


- 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.
- To immediately remove access, revoke issued tokens.
Copy link
Contributor

Choose a reason for hiding this comment

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

Link to revocation.

* `my-chat-room` or
* `dms:*` or
* `*`
* `my-chat-room::$chat` - a specific room
Copy link
Contributor

Choose a reason for hiding this comment

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

These changes are incorrect.

@@ -0,0 +1,156 @@
---
title: Spaces authentication
Copy link
Contributor

Choose a reason for hiding this comment

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

I think the same changes for Chat need to be applied here too. The only thing I'm not 100% on is the directive usage for Spaces, but I'm pretty sure it's the same as per Chat now.

…ti-language examples, and consolidate duplicated content
# Conflicts:
#	src/pages/docs/platform/errors/codes.mdx
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 think there's quite a bit still to do here. Please see comments

| <If lang="javascript,nodejs,java,objc,swift">key</If><If lang="csharp">Key</If><If lang="ruby">:key</If> | Optionally the [API key](/docs/auth#api-key) to use can be specified as a full key string; if not, the API key passed into [`ClientOptions`](#client-options) when instancing the Realtime or REST library is used | `String` |
| <If lang="javascript,nodejs,java,objc,swift">queryTime</If><If lang="csharp,go">QueryTime</If><If lang="ruby">:query_time</If> | _false_ If true, the library will query the Ably servers for the current time when [issuing TokenRequests](/docs/auth/token) instead of relying on a locally-available time of day. Knowing the time accurately is needed to create valid signed Ably [TokenRequests](/docs/auth/token), so this option is useful for library instances on auth servers where for some reason the server clock cannot be kept synchronized through normal means, such as an [NTP daemon](https://en.wikipedia.org/wiki/Ntpd) . The server is queried for the current time once per client library instance (which stores the offset from the local clock), so if using this option you should avoid instancing a new version of the library for each request. | `Boolean` |
| <If lang="javascript,nodejs,java,objc,swift">token</If><If lang="csharp,go">Token</If><If lang="ruby">:token</If> | An authenticated token. This can either be a [`TokenDetails`](/docs/api/realtime-sdk/types#token-details) object, a [`TokenRequest`](/docs/api/realtime-sdk/types#token-request) object, or token string (obtained from the <If lang="javascript,nodejs,java,objc,swift">`token`</If><If lang="csharp,go">`Token`</If> property of a [`TokenDetails`](/docs/api/realtime-sdk/types#token-details) component of an Ably TokenRequest response, or a [JSON Web Token](https://tools.ietf.org/html/rfc7519) satisfying [the Ably requirements for JWTs](/docs/auth/token#jwt)). This option is mostly useful for testing: since tokens are short-lived, in production you almost always want to use an authentication method that allows the client library to renew the token automatically when the previous one expires, such as <If lang="javascript,nodejs,java,objc,swift">`authUrl`</If><If lang="csharp">AuthUrl</If><If lang="ruby">:auth_url</If><If lang="python">auth_url</If> or <If lang="javascript,nodejs,java,objc,swift">authCallback</If><If lang="csharp">AuthCallback</If><If lang="python">auth_callback</If><If lang="ruby">:auth_callback</If>. Read more about [Token authentication](/docs/auth/token) | `String`, `TokenDetails` or `TokenRequest` |
| <If lang="javascript,nodejs,java,objc,swift">token</If><If lang="csharp,go">Token</If><If lang="ruby">:token</If> | An authenticated token. This can either be a [`TokenDetails`](/docs/api/realtime-sdk/types#token-details) object, a [`TokenRequest`](/docs/api/realtime-sdk/types#token-request) object, or token string (obtained from the <If lang="javascript,nodejs,java,objc,swift">`token`</If><If lang="csharp,go">`Token`</If> property of a [`TokenDetails`](/docs/api/realtime-sdk/types#token-details) component of an Ably TokenRequest response, or a [JSON Web Token](https://tools.ietf.org/html/rfc7519) satisfying [the Ably requirements for JWTs](/docs/auth/jwt)). This option is mostly useful for testing: since tokens are short-lived, in production you almost always want to use an authentication method that allows the client library to renew the token automatically when the previous one expires, such as <If lang="javascript,nodejs,java,objc,swift">`authUrl`</If><If lang="csharp">AuthUrl</If><If lang="ruby">:auth_url</If><If lang="python">auth_url</If> or <If lang="javascript,nodejs,java,objc,swift">authCallback</If><If lang="csharp">AuthCallback</If><If lang="python">auth_callback</If><If lang="ruby">:auth_callback</If>. Read more about [Token authentication](/docs/auth/token) | `String`, `TokenDetails` or `TokenRequest` |
Copy link
Member

Choose a reason for hiding this comment

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

An authenticated token

I realise that this wording was here before this PR, but I don't think this is correct. I think we should refer to this as an "authentication token".

meta_keywords: "Ably Token, TokenRequest, token authentication, native token, capabilities, token request, embedded token JWT"
---

Ably Tokens are the native token formats for token authentication. Use native Ably Tokens when:
Copy link
Member

Choose a reason for hiding this comment

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

I think this introductory section should say a bit more to give the reader context.

The principal way that token authentication is supported in Ably is JWT tokens...). However, Ably tokens relate to an alternative mechanism that predates Ably's support for JWT. Unlike JWTs, Ably tokens aren't generated by a client but are issued by the Ably service via a /requestToken endpoint; a client generates a signed Token Request and this is exchanged for a token by the Ably service. This means that, in general, integrating an application to use Ably tokens is more involved; Ably tokens also do not support all of the functionality now available with JWTs. However, there are still some circumstances where the use of Ably tokens is recommended:
.. etc


- Your capability list is too large and exceeds JWT size limits (JWTs must fit within HTTP header limits, typically around 8 KB). Use a TokenRequest or Ably Token.
- You need to keep your capability list confidential, as JWTs can be decoded by clients.
- You already have a JWT-based auth system and want to embed Ably tokens within your existing JWTs.
Copy link
Member

Choose a reason for hiding this comment

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

This doesn't make any sense. You have to have some reason to be using Ably tokens in the first place. Then, separately, you might have a need to wrap them. If you want to wrap tokens, you can also do that with JWTs, so this by itself isn't a reason to use Ably tokens.

- You need to keep your capability list confidential, as JWTs can be decoded by clients.
- You already have a JWT-based auth system and want to embed Ably tokens within your existing JWTs.

Token formats are composable. For example, you can wrap Ably credentials in an outer JWT used by your application while still using JWT-based or native Ably token flows underneath.
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 true, but not relevant to this section.


## Choosing between TokenRequest and Ably Token (direct)

Ably Tokens can be issued in two ways:
Copy link
Member

Choose a reason for hiding this comment

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

Ably tokens are only ever issued in one way. This discussion is about who performs which part(s) of the process. This should be clearer


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).
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
* 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).
* An [`authUrl`](/docs/api/realtime-sdk/types#client-options) or [`authCallback`](/docs/api/realtime-sdk/types#client-options) is provided.

* [`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.
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
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.
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 as the current token expires.


## Server setup

Create an endpoint that validates users and returns JWTs with the appropriate Chat capabilities:
Copy link
Member

Choose a reason for hiding this comment

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

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

@@ -0,0 +1,322 @@
---
Copy link
Member

Choose a reason for hiding this comment

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

This change shouldn't be in this PR


<Aside data-type='important'>
The examples use [basic authentication](/docs/auth/basic) to demonstrate features for convenience. In your own applications, basic authentication should never be used on the client-side as it exposes your Ably API key. Instead use [token authentication](/docs/auth/token).
Client-side applications must use [JWT authentication](/docs/auth/jwt). API keys should never be exposed in client-side code because they don't expire and cannot be scoped to specific users.
Copy link
Member

Choose a reason for hiding this comment

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

It's not a hard requirement to support JWT. I think this should say that Client-side applications must use token auth

…suance flows, fix cross-references, and consolidate content
@m-hulbert m-hulbert temporarily deployed to ably-docs-authchanges-77ycefvs February 24, 2026 11:40 Inactive
Copy link
Contributor

@m-hulbert m-hulbert left a comment

Choose a reason for hiding this comment

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

This is pretty much there on the main authentication section - just a few odd choices on the Chat and Spaces pages 👍

Comment on lines +36 to +38
See [JWT authentication](/docs/auth/jwt) for server and client setup examples.

"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>
An [identified client](/docs/auth/identified-clients) has a verified identity (`clientId`) set by the token issuer.
Copy link
Contributor

Choose a reason for hiding this comment

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

These two lines seem quite out of place.

Capabilities can be set when creating a token or token request, as shown in the following example:
#### Using JWT (recommended) <a id="jwt-capabilities"/>

Set capabilities in a JWT using the `x-ably-capability` claim. No Ably SDK is required. This example uses [jsonwebtoken](https://www.npmjs.com/package/jsonwebtoken):
Copy link
Contributor

Choose a reason for hiding this comment

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

Only the JS example uses that package.

If an API key must be shared with a third party, then it is recommended that [the principle of least privilege](https://en.wikipedia.org/wiki/Principle_of_least_privilege) is considered, assigning only the capabilities needed by that third party. Thus, any Ably requests authenticated using that API key or Ably-compatible tokens associated with that API key, will be restricted to the capabilities assigned to the API key.

Capabilities can be set when creating a token or token request, as shown in the following example:
#### Using JWT (recommended) <a id="jwt-capabilities"/>
Copy link
Contributor

Choose a reason for hiding this comment

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

Rather than having recommended and alternative in the headings, can we have that in the opening text instead?

```
</Code>

```go
Copy link
Contributor

Choose a reason for hiding this comment

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

Is there a reason we've removed the code examples from other languages? I think we can update these with what you've added in the other files rather than lose them.

}
tokenRequest, _ := rest.Auth.CreateTokenRequest(params)
<Code>
```javascript
Copy link
Contributor

Choose a reason for hiding this comment

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

With JWTs we could make this text and not have an example in all languages rather than linking out to another page for the info, but for TokenRequests I think it wouldn't hurt to give an example in all languages - seems odd to only provide 2 and then tell people to go elsewhere for the other 4/5.

final ablyJwt = "$base64Header.$base64Claims.$signature";
```
</Code>
## Embedded Token JWT <a id="embedded"/>
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure this fits here. Should it go on the ably tokens page do you think?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It was there previously but I moved it up a level since it applies to both token types...

#3085 (comment)

meta_keywords: "Ably Token, TokenRequest, token authentication, native token, capabilities, token request, embedded token JWT"
---

The primary way that token authentication is supported in Ably is [JWTs](/docs/auth/jwt). However, Ably tokens are an alternative mechanism that predates Ably's support for JWT. Unlike JWTs, Ably tokens are not generated by a client but are issued by the Ably service via a `/requestToken` endpoint; a client generates a signed *Token Request* and this is exchanged for a token by the Ably service. This means that, in general, integrating an application to use Ably tokens is more involved; Ably tokens also do not support all of the functionality now available with JWTs. However, there are still some circumstances where the use of Ably tokens is recommended:
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
The primary way that token authentication is supported in Ably is [JWTs](/docs/auth/jwt). However, Ably tokens are an alternative mechanism that predates Ably's support for JWT. Unlike JWTs, Ably tokens are not generated by a client but are issued by the Ably service via a `/requestToken` endpoint; a client generates a signed *Token Request* and this is exchanged for a token by the Ably service. This means that, in general, integrating an application to use Ably tokens is more involved; Ably tokens also do not support all of the functionality now available with JWTs. However, there are still some circumstances where the use of Ably tokens is recommended:
Ably tokens are an alternative mechanism for authenticating with Ably.
They are not generated by a client but are issued by the Ably service via a `/requestToken` endpoint; a client generates a signed `Token Request` and this is exchanged for a token by the Ably service. Generally, integrating an application to use Ably tokens is more involved as Ably tokens also do not support all of the functionality available to JWTs.
[JWTs](/docs/auth/jwt) are the recommended mechanism for authenticating with Ably, however there are still some circumstances where the use of Ably tokens may be preferred:

```
</Code>

## Client setup
Copy link
Contributor

Choose a reason for hiding this comment

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

These shouldn't be prefixed with realtime_ as there is only a single Chat interface. Also many of these are redundant on the client because we only have JS, React, Swift and Kotlin SDKs available - we're missing React and have a raft of others that don't exist.

Never use API keys in client-side code. API keys do not expire and are not suitable for untrusted clients.
</Aside>

## Spaces capabilities
Copy link
Contributor

Choose a reason for hiding this comment

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

The order of items on the page should match chat please.

```
</Code>

## Client examples
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment as for Chat, however Spaces only supports JS and React.

@umair-ably umair-ably requested a review from m-hulbert March 2, 2026 08:33
# Conflicts:
#	src/pages/docs/auth/capabilities.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