Skip to content

Commit cf3edfd

Browse files
rainbowFiclaude
andcommitted
Replace Ably token requests with JWT signing
Switch from Ably SDK's createTokenRequest to direct JWT signing using the jsonwebtoken library, matching the pattern in ably-labs/NextJS-chat-app#16 and the Chat SDK docs. - Auth function now signs a JWT with the Ably key secret instead of instantiating an Ably.Rest client - Chat component uses authCallback instead of authUrl to pass the JWT token string directly to the Ably realtime client Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 029421c commit cf3edfd

4 files changed

Lines changed: 2155 additions & 2828 deletions

File tree

components/Chat.tsx

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,18 @@ export default function Chat() {
1111

1212
useEffect(() => {
1313
const clientId = `ably-chat-demo-user-${Math.random().toString(36).substring(2, 10)}`;
14-
const realtimeClient = new Ably.Realtime({ authUrl: `/api/auth?clientId=${clientId}`, clientId });
14+
const realtimeClient = new Ably.Realtime({
15+
authCallback: async (_tokenParams, callback) => {
16+
try {
17+
const response = await fetch(`/api/auth?clientId=${clientId}`);
18+
const token = await response.text();
19+
callback(null, token);
20+
} catch (error) {
21+
callback(error as Ably.ErrorInfo, null);
22+
}
23+
},
24+
clientId,
25+
});
1526
const ablyChatClient = new ChatClient(realtimeClient);
1627

1728
setChatClient(ablyChatClient);

netlify/functions/auth.ts

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
1-
import Ably from "ably";
1+
import jwt from 'jsonwebtoken';
22
import { HandlerEvent } from '@netlify/functions';
33

4-
54
export async function handler(event: HandlerEvent) {
65
if (!process.env.ABLY_API_KEY) {
76
console.error('Missing ABLY_API_KEY environment variable.')
@@ -13,16 +12,21 @@ export async function handler(event: HandlerEvent) {
1312
}
1413

1514
const clientId = event.queryStringParameters?.['clientId'] || 'NO_CLIENT_ID_PROVIDED';
16-
const client = new Ably.Rest(process.env.ABLY_API_KEY);
17-
const tokenRequest = await client.auth.createTokenRequest({
18-
capability: {
19-
'[chat]*': ['*'],
20-
},
21-
clientId: clientId,
22-
});
15+
const [keyName, keySecret] = process.env.ABLY_API_KEY.split(':');
16+
17+
const now = Math.floor(Date.now() / 1000);
18+
const claims = {
19+
'x-ably-capability': JSON.stringify({ '*': ['*'] }),
20+
'x-ably-clientId': clientId,
21+
iat: now,
22+
exp: now + 3600,
23+
};
24+
25+
const token = jwt.sign(claims, keySecret, { algorithm: 'HS256', keyid: keyName });
26+
2327
return {
2428
statusCode: 200,
25-
headers: { 'content-type': 'application/json' },
26-
body: JSON.stringify(tokenRequest)
29+
headers: { 'content-type': 'application/jwt' },
30+
body: token,
2731
}
2832
}

0 commit comments

Comments
 (0)