Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions examples/auth-generate-jwt/javascript/src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const config = {
AUTH_URL: import.meta.env.VITE_AUTH_JWT_URL as string,
};
11 changes: 10 additions & 1 deletion examples/auth-generate-jwt/javascript/src/script.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as Ably from 'ably';
import './styles.css';
import { config } from './config';

const connectButton = document.querySelector('button') as HTMLButtonElement;

Expand All @@ -14,7 +15,15 @@ function handleConnect() {
messageOne.textContent = '✓';

const realtimeClient = new Ably.Realtime({
authUrl: 'http://localhost:3001/generate-jwt',
authCallback: async (_tokenParams, callback) => {
try {
const response = await fetch(config.AUTH_URL || 'http://localhost:3001/generate-jwt');
const token = await response.text();
callback(null, token);
} catch (error) {
callback(error instanceof Error ? error.message : String(error), null);
}
},
});

const messageTwo = document.getElementById('message-2');
Expand Down
1 change: 1 addition & 0 deletions examples/auth-generate-jwt/javascript/vite-env.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
interface ImportMetaEnv {
readonly VITE_ABLY_KEY: string;
readonly VITE_AUTH_URL: string;
// Add other environment variables here if needed
}

Expand Down
33 changes: 30 additions & 3 deletions examples/auth-generate-jwt/react/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import React, { useState, useEffect } from 'react';
import React, { useState } from 'react';
import * as Ably from 'ably';
import { AblyProvider, useConnectionStateListener } from 'ably/react';
import './styles/styles.css';
import { config } from './config';

interface StatusMessage {
id: number;
Expand Down Expand Up @@ -53,10 +54,36 @@ export default function App() {
]);

const handleConnect = async () => {
// Navigate to authenticated page
window.location.href = '/authenticated';
// Update first message
setMessages((prevMessages) => prevMessages.map((msg) => (msg.id === 1 ? { ...msg, success: true } : msg)));

// Initialize Ably client with JWT auth
const realtimeClient = new Ably.Realtime({
authCallback: async (_tokenParams, callback) => {
try {
const response = await fetch(config.AUTH_URL || 'http://localhost:3001/generate-jwt');
const token = await response.text();
callback(null, token);
} catch (error) {
callback(error instanceof Error ? error.message : String(error), null);
}
},
});

// Update second message
setMessages((prevMessages) => prevMessages.map((msg) => (msg.id === 2 ? { ...msg, success: true } : msg)));

setClient(realtimeClient);
};

if (client) {
return (
<AblyProvider client={client}>
<StatusMessages messages={messages} setMessages={setMessages} />
</AblyProvider>
);
}

return (
<div className="flex items-center justify-center min-h-screen bg-gray-100">
<div className="bg-white shadow-md rounded-md p-8 w-[50%] flex flex-col">
Expand Down
3 changes: 3 additions & 0 deletions examples/auth-generate-jwt/react/src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const config = {
AUTH_URL: import.meta.env.VITE_AUTH_JWT_URL as string,
};
1 change: 1 addition & 0 deletions examples/auth-generate-jwt/react/src/env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

interface ImportMetaEnv {
readonly VITE_ABLY_KEY: string;
readonly VITE_AUTH_JWT_URL: string;
}

interface ImportMeta {
Expand Down
7 changes: 3 additions & 4 deletions examples/auth-generate-jwt/server/src/server.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import express from 'express';
import path from 'path';
import { fileURLToPath } from 'url';
import dotenv from 'dotenv';
import cors from 'cors';
import crypto from 'crypto';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
dotenv.config({ path: path.resolve(__dirname, '../../../.env.local') });

const app = express();
Expand All @@ -21,8 +23,6 @@ function base64urlEncode(str: string) {
}

app.get('/generate-jwt', async (_req, res) => {
console.log('1 - /generate-jwt endpoint called');

const ablyApiKey = process.env.VITE_ABLY_KEY || '';
const [apiKeyName, apiKeySecret] = ablyApiKey.split(':');
try {
Expand Down Expand Up @@ -51,8 +51,7 @@ app.get('/generate-jwt', async (_req, res) => {
const signature = base64urlEncode(hmac.digest('base64'));
const ablyJwt = base64Header + '.' + base64Claims + '.' + signature;

console.log('2 - JWT generated: ', ablyJwt);
res.json(ablyJwt);
res.type('application/jwt').send(ablyJwt);
} catch (error) {
res.status(500).json({ error: 'Failed to generate token' });
}
Expand Down
3 changes: 3 additions & 0 deletions examples/auth-request-token/javascript/src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const config = {
AUTH_URL: import.meta.env.VITE_AUTH_TOKEN_URL as string,
};
11 changes: 10 additions & 1 deletion examples/auth-request-token/javascript/src/script.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as Ably from 'ably';
import './styles.css';
import { config } from './config';

const connectButton = document.querySelector('button') as HTMLButtonElement;

Expand All @@ -14,7 +15,15 @@ function handleConnect() {
messageOne.textContent = '✓';

const realtimeClient = new Ably.Realtime({
authUrl: 'http://localhost:3001/request-token',
authCallback: async (_tokenParams, callback) => {
try {
const response = await fetch(config.AUTH_URL || 'http://localhost:3001/request-token');
const token = await response.text();
callback(null, token);
} catch (error) {
callback(error instanceof Error ? error.message : String(error), null);
}
},
});

const messageTwo = document.getElementById('message-2');
Expand Down
1 change: 1 addition & 0 deletions examples/auth-request-token/javascript/vite-env.d.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
interface ImportMetaEnv {
readonly VITE_ABLY_KEY: string;
readonly VITE_AUTH_TOKEN_URL: string;
// Add other environment variables here if needed
}

Expand Down
31 changes: 29 additions & 2 deletions examples/auth-request-token/react/src/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React, { useState, useEffect } from 'react';
import * as Ably from 'ably';
import { AblyProvider, useConnectionStateListener } from 'ably/react';
import './styles/styles.css';
import { config } from './config';

interface StatusMessage {
id: number;
Expand Down Expand Up @@ -53,10 +54,36 @@ export default function App() {
]);

const handleConnect = async () => {
// Navigate to authenticated page
window.location.href = '/authenticated';
// Update first message
setMessages((prevMessages) => prevMessages.map((msg) => (msg.id === 1 ? { ...msg, success: true } : msg)));

// Initialize Ably client with token auth
const realtimeClient = new Ably.Realtime({
authCallback: async (_tokenParams, callback) => {
try {
const response = await fetch(config.AUTH_URL || 'http://localhost:3001/request-token');
const token = await response.text();
callback(null, token);
} catch (error) {
callback(error instanceof Error ? error.message : String(error), null);
}
},
});

// Update second message
setMessages((prevMessages) => prevMessages.map((msg) => (msg.id === 2 ? { ...msg, success: true } : msg)));

setClient(realtimeClient);
};

if (client) {
return (
<AblyProvider client={client}>
<StatusMessages messages={messages} setMessages={setMessages} />
</AblyProvider>
);
}

return (
<div className="flex items-center justify-center min-h-screen bg-gray-100">
<div className="bg-white shadow-md rounded-md p-8 w-[50%] flex flex-col">
Expand Down
3 changes: 3 additions & 0 deletions examples/auth-request-token/react/src/config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export const config = {
AUTH_URL: import.meta.env.VITE_AUTH_TOKEN_URL as string,
};
1 change: 1 addition & 0 deletions examples/auth-request-token/react/src/env.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

interface ImportMetaEnv {
readonly VITE_ABLY_KEY: string;
readonly VITE_AUTH_TOKEN_URL: string;
}

interface ImportMeta {
Expand Down
4 changes: 2 additions & 2 deletions examples/auth-request-token/server/src/server.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import express from 'express';
import path from 'path';
import { fileURLToPath } from 'url';
import dotenv from 'dotenv';
import cors from 'cors';
import Ably from 'ably';

const __dirname = path.dirname(fileURLToPath(import.meta.url));
dotenv.config({ path: path.resolve(__dirname, '../../../.env.local') });

const app = express();
Expand All @@ -19,10 +21,8 @@ app.use(
const ably = new Ably.Rest(process.env.VITE_ABLY_KEY || '');

app.get('/request-token', async (_req, res) => {
console.log('1 - /request-token endpoint called');
try {
const tokenRequest = await ably.auth.requestToken({ clientId: 'example-client-id' });
console.log('2 - Token generated:', tokenRequest);
res.json(tokenRequest);
} catch (error) {
res.status(500).json({ error: 'Failed to generate token' });
Expand Down
2 changes: 2 additions & 0 deletions src/components/Examples/ExamplesRenderer.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ const ExamplesRenderer = ({
Object.entries(files).forEach(([languageKey, languageFiles]) => {
result[languageKey as LanguageKey] = updateAblyConnectionKey(languageFiles, apiKey, {
NAME: getRandomChannelName(), // Use CHANNEL_NAME as env var key
AUTH_TOKEN_URL: process.env.VITE_AUTH_TOKEN_URL || '',
AUTH_JWT_URL: process.env.VITE_AUTH_JWT_URL || '',
});
});
return result;
Expand Down
20 changes: 20 additions & 0 deletions src/data/examples/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,26 @@ export const examples: Example[] = [
metaTitle: 'Build AI message-per-response streaming with Ably AI Transport',
metaDescription: `Stream AI-generated tokens by appending them to a single message using Ably AI Transport. Each response appears as one compacted message in channel history.`,
},
{
id: 'auth-generate-jwt',
name: 'Generate JWT',
description: 'Generate a JSON Web Token (JWT) for authenticating users.',
products: ['auth'],
layout: 'single-horizontal',
visibleFiles: ['src/script.ts', 'App.tsx', 'Chat.tsx', 'Home.tsx', 'index.tsx'],
metaTitle: `Authenticate with Ably using JWTs`,
metaDescription: `Learn how to generate and use JWTs for client authentication with Ably. Secure token-based auth for realtime applications.`,
},
{
id: 'auth-request-token',
name: 'Request Token',
description: 'Request an Ably Token for authenticating users.',
products: ['auth'],
layout: 'single-horizontal',
visibleFiles: ['src/script.ts', 'App.tsx', 'Chat.tsx', 'Home.tsx', 'index.tsx'],
metaTitle: `Authenticate with Ably Token`,
metaDescription: `Learn how to request and use Ably Tokens for client authentication. Secure token-based auth for realtime applications.`,
},
{
id: 'chat-presence',
name: 'Chat presence',
Expand Down