[FTF-468] Several docs changes to highlight token auth over API key auth, as well as more info on using JWTs#3085
[FTF-468] Several docs changes to highlight token auth over API key auth, as well as more info on using JWTs#3085umair-ably wants to merge 8 commits intomainfrom
Conversation
|
Important Review skippedAuto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the You can disable this status message by setting the Use the checkbox below for a quick retry:
✨ Finishing Touches🧪 Generate unit tests (beta)
Tip Try Coding Plans. Let us write the prompt for your AI agent so you can ship faster (with fewer bugs). 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. Comment |
paddybyers
left a comment
There was a problem hiding this comment.
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', |
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
Why is this using native tokens, instead of generating a JWT?
| ``` | ||
| </Code> | ||
|
|
||
| ## Security comparison |
There was a problem hiding this comment.
I'm not convinced this section adds anything. It feels like slop.
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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?
There was a problem hiding this comment.
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?
src/pages/docs/auth/token.mdx
Outdated
|
|
||
| ### TokenRequest <a id="choosing-tokenrequest"/> | ||
|
|
||
| **Best for:** Standard web and mobile applications using Ably SDKs. |
There was a problem hiding this comment.
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'> |
There was a problem hiding this comment.
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. |
|
|
||
| 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'> |
There was a problem hiding this comment.
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.
src/pages/docs/chat/rooms/typing.mdx
Outdated
| 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. |
There was a problem hiding this comment.
I don't understand why this comment is here. Doesn't the chat SDK ensure that a client is always identified?
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
Again, we should be recommending JWT auth.
mattheworiordan
left a comment
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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', { |
There was a problem hiding this comment.
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}` }, |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
If that's teh case, why are you not specifying a TTL when issuing the token?
| ``` | ||
| </Code> | ||
|
|
||
| ## Integrating with AWS Cognito <a id="cognito"/> |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
Why have you introduced Next Steps? We've not used this in the docs.
src/pages/docs/chat/rooms/typing.mdx
Outdated
| 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. |
There was a problem hiding this comment.
Yes it does, this is needless information as they cannot connect without a clientId
src/pages/docs/spaces/avatar.mdx
Outdated
| 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. |
There was a problem hiding this comment.
This is not necessary. If this is needed, the problem of which auth mechanism t use is surely solved?
8d4649e to
4e56d1a
Compare
|
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)
Comments on auth/token.mdx (8 comments)
Comments on auth/jwt-integration.mdx (8 comments)
Comments on chat/authentication.mdx (12 comments)
Comments on Chat Room Features (6 comments)
Comments on chat/setup.mdx (1 comment)
Comments on spaces/authentication.mdx & spaces/avatar.mdx (2 comments)
Key Changes Made
|
…ll as more info on using JWTs
4e56d1a to
0d61283
Compare
0906ade to
43cd265
Compare
43cd265 to
2115ab9
Compare
2115ab9 to
4b0b630
Compare
paddybyers
left a comment
There was a problem hiding this comment.
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 |
4b0b630 to
f76e713
Compare
|
@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 |
f76e713 to
6e4871d
Compare
|
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) |
src/pages/docs/protocols/mqtt.mdx
Outdated
|
|
||
| ### JWT Authentication <a id="jwt-auth"/> | ||
|
|
||
| <Aside data-type='note'> |
There was a problem hiding this comment.
remove this... duplicate
178dc16 to
0854b3e
Compare
…ll as more info on using JWTs
0854b3e to
3a2d796
Compare
|
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:
cc: @m-hulbert |
paddybyers
left a comment
There was a problem hiding this comment.
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 )
src/pages/docs/auth/capabilities.mdx
Outdated
| 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: |
There was a problem hiding this comment.
| Set capabilities in a JWT using the `x-ably-capability` claim. No Ably SDK is required—any 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
There was a problem hiding this comment.
Maybe worth just adding
This example uses jsonwebtoken
?
src/pages/docs/auth/capabilities.mdx
Outdated
| capability := map[string][]string{ | ||
| "*": {"*"}, | ||
| } | ||
| If JWT is not suitable, use the Ably SDK to create a TokenRequest with capabilities: |
There was a problem hiding this comment.
This says nothing about why JWT might not be suitable
src/pages/docs/auth/capabilities.mdx
Outdated
|
|
||
| ### 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. |
There was a problem hiding this comment.
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.
src/pages/docs/auth/capabilities.mdx
Outdated
| ## 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. |
There was a problem hiding this comment.
@m-hulbert Are we happy that "TokenRequest authentication" is the appropriate name in these docs for the native token mechanism?
There was a problem hiding this comment.
I think the high-level mechanism should be 'Ably Tokens' personally.
src/pages/docs/auth/capabilities.mdx
Outdated
|
|
||
| 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. |
There was a problem hiding this comment.
Note that this does not apply to presence
I thought we support that now - pls check
src/pages/docs/auth/token.mdx
Outdated
| * 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). |
There was a problem hiding this comment.
| 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). |
src/pages/docs/auth/token.mdx
Outdated
|
|
||
| ### Multi-tenant SaaS with user roles <a id="scenario-multitenant"/> | ||
|
|
||
| **Recommendation: Ably JWT with channel claims** |
There was a problem hiding this comment.
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?
src/pages/docs/auth/token.mdx
Outdated
| ``` | ||
| </Code> | ||
|
|
||
| Other clients can read these trusted claims from presence or message metadata. |
There was a problem hiding this comment.
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'], |
There was a problem hiding this comment.
I think this is incorrect. A resource specifier in a capability expression will match on the channel name without the directive part.
src/pages/docs/chat/setup.mdx
Outdated
|
|
||
| <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. |
There was a problem hiding this comment.
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
left a comment
There was a problem hiding this comment.
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.
authCallbackused in examples in all languages -authUrlcan 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.
- Just info on JWTs with a mention at the top that it's recommended.
- 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?
src/pages/docs/auth/token.mdx
Outdated
|
|
||
| ## Token mechanism comparison <a id="comparison"/> | ||
|
|
||
| | Feature | Ably JWT (Recommended) | Embedded JWT | TokenRequest | |
There was a problem hiding this comment.
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.
src/pages/docs/auth/token.mdx
Outdated
|
|
||
| | Feature | Ably JWT (Recommended) | Embedded JWT | TokenRequest | | ||
| |---------|:----------------------:|:------------:|:------------:| | ||
| | **Server SDK required** | No | Yes | Yes | |
There was a problem hiding this comment.
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). |
There was a problem hiding this comment.
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 | |
There was a problem hiding this comment.
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(':'); |
There was a problem hiding this comment.
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) |
There was a problem hiding this comment.
Can we ensure links are included inline rather than having 'see X' or 'read more' everywhere please.
| @@ -0,0 +1,115 @@ | |||
| --- | |||
| title: Spaces authentication | |||
There was a problem hiding this comment.
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: |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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> |
- Adds full code examples to product-specific auth pages - Updates nav and cross-references to highlight token auth over API key auth
m-hulbert
left a comment
There was a problem hiding this comment.
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.
src/pages/docs/auth/index.mdx
Outdated
| 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 | |
There was a problem hiding this comment.
I'm not sure 'Ably Tokens' is the correct term here to encompass JWT and what we're referring to as 'Ably Tokens'.
src/pages/docs/auth/index.mdx
Outdated
|
|
||
| "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. |
There was a problem hiding this comment.
| **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. |
src/pages/docs/auth/index.mdx
Outdated
| </Aside> | ||
|
|
||
| "Authenticated client" is a client of the Ably service that has been successfully authenticated. | ||
| ### Quick start |
There was a problem hiding this comment.
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.
src/pages/docs/auth/index.mdx
Outdated
| ## 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). |
There was a problem hiding this comment.
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.
src/pages/docs/auth/index.mdx
Outdated
| ## 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. |
There was a problem hiding this comment.
| 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 |
There was a problem hiding this comment.
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. |
There was a problem hiding this comment.
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. |
src/pages/docs/chat/setup.mdx
Outdated
| * `my-chat-room` or | ||
| * `dms:*` or | ||
| * `*` | ||
| * `my-chat-room::$chat` - a specific room |
There was a problem hiding this comment.
These changes are incorrect.
| @@ -0,0 +1,156 @@ | |||
| --- | |||
| title: Spaces authentication | |||
There was a problem hiding this comment.
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
43247db to
894a362
Compare
# Conflicts: # src/pages/docs/platform/errors/codes.mdx
894a362 to
954ac84
Compare
paddybyers
left a comment
There was a problem hiding this comment.
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` | |
There was a problem hiding this comment.
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".
src/pages/docs/auth/ably-tokens.mdx
Outdated
| 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: |
There was a problem hiding this comment.
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
src/pages/docs/auth/ably-tokens.mdx
Outdated
|
|
||
| - 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. |
There was a problem hiding this comment.
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.
src/pages/docs/auth/ably-tokens.mdx
Outdated
| - 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. |
There was a problem hiding this comment.
This is true, but not relevant to this section.
src/pages/docs/auth/ably-tokens.mdx
Outdated
|
|
||
| ## Choosing between TokenRequest and Ably Token (direct) | ||
|
|
||
| Ably Tokens can be issued in two ways: |
There was a problem hiding this comment.
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
src/pages/docs/auth/token.mdx
Outdated
|
|
||
| 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). |
There was a problem hiding this comment.
| * 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. |
src/pages/docs/auth/token.mdx
Outdated
| * [`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. |
There was a problem hiding this comment.
| 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: |
There was a problem hiding this comment.
| 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 @@ | |||
| --- | |||
There was a problem hiding this comment.
This change shouldn't be in this PR
src/pages/docs/spaces/setup.mdx
Outdated
|
|
||
| <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. |
There was a problem hiding this comment.
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
00e0ffe to
95ef6b7
Compare
m-hulbert
left a comment
There was a problem hiding this comment.
This is pretty much there on the main authentication section - just a few odd choices on the Chat and Spaces pages 👍
src/pages/docs/auth/index.mdx
Outdated
| 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. |
There was a problem hiding this comment.
These two lines seem quite out of place.
src/pages/docs/auth/capabilities.mdx
Outdated
| 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): |
There was a problem hiding this comment.
Only the JS example uses that package.
src/pages/docs/auth/capabilities.mdx
Outdated
| 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"/> |
There was a problem hiding this comment.
Rather than having recommended and alternative in the headings, can we have that in the opening text instead?
| ``` | ||
| </Code> | ||
|
|
||
| ```go |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
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"/> |
There was a problem hiding this comment.
I'm not sure this fits here. Should it go on the ably tokens page do you think?
There was a problem hiding this comment.
It was there previously but I moved it up a level since it applies to both token types...
src/pages/docs/auth/ably-tokens.mdx
Outdated
| 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: |
There was a problem hiding this comment.
| 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 |
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
The order of items on the page should match chat please.
| ``` | ||
| </Code> | ||
|
|
||
| ## Client examples |
There was a problem hiding this comment.
Same comment as for Chat, however Spaces only supports JS and React.
# Conflicts: # src/pages/docs/auth/capabilities.mdx
Description
Motivations/Objectives:
Checklist