or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

authentication.mdchannel-communication.mdclient-management.mdconnection-management.mdindex.md

authentication.mddocs/

0

# Authentication

1

2

Authentication and authorization system for private channels, presence channels, and user authentication with customizable auth handlers.

3

4

## Capabilities

5

6

### Channel Authorization Options

7

8

Configuration for private and presence channel authentication.

9

10

```typescript { .api }

11

/**

12

* Channel authorization configuration

13

*/

14

interface ChannelAuthorizationOptions {

15

transport: 'ajax' | 'jsonp';

16

endpoint: string;

17

params?: any;

18

headers?: any;

19

paramsProvider?: () => any;

20

headersProvider?: () => any;

21

customHandler?: ChannelAuthorizationHandler;

22

}

23

24

/**

25

* Channel authorization request parameters

26

*/

27

interface ChannelAuthorizationRequestParams {

28

socketId: string;

29

channelName: string;

30

}

31

32

/**

33

* Channel authorization response data

34

*/

35

interface ChannelAuthorizationData {

36

auth: string;

37

channel_data?: string;

38

shared_secret?: string;

39

}

40

41

/**

42

* Channel authorization callback function

43

*/

44

type ChannelAuthorizationCallback = (

45

error: Error | null,

46

authData: ChannelAuthorizationData | null

47

) => void;

48

49

/**

50

* Custom channel authorization handler

51

*/

52

interface ChannelAuthorizationHandler {

53

(params: ChannelAuthorizationRequestParams, callback: ChannelAuthorizationCallback): void;

54

}

55

```

56

57

**Channel Authorization Examples:**

58

59

```typescript

60

// Basic endpoint authorization

61

const pusher = new Pusher("app-key", {

62

cluster: "us2",

63

channelAuthorization: {

64

endpoint: "/pusher/auth",

65

transport: "ajax"

66

}

67

});

68

69

// Authorization with custom headers and parameters

70

const pusher = new Pusher("app-key", {

71

cluster: "us2",

72

channelAuthorization: {

73

endpoint: "/api/pusher/auth",

74

transport: "ajax",

75

headers: {

76

"X-CSRF-Token": "csrf-token",

77

"Authorization": "Bearer token"

78

},

79

params: {

80

userId: "123"

81

}

82

}

83

});

84

85

// Dynamic headers and parameters

86

const pusher = new Pusher("app-key", {

87

cluster: "us2",

88

channelAuthorization: {

89

endpoint: "/pusher/auth",

90

transport: "ajax",

91

headersProvider: () => ({

92

"Authorization": `Bearer ${getCurrentToken()}`,

93

"X-User-ID": getCurrentUserId()

94

}),

95

paramsProvider: () => ({

96

timestamp: Date.now(),

97

nonce: generateNonce()

98

})

99

}

100

});

101

102

// Custom authorization handler

103

const pusher = new Pusher("app-key", {

104

cluster: "us2",

105

channelAuthorization: {

106

endpoint: "/pusher/auth", // Still required but not used

107

transport: "ajax",

108

customHandler: (params, callback) => {

109

// Custom authorization logic

110

fetch("/api/custom-auth", {

111

method: "POST",

112

headers: { "Content-Type": "application/json" },

113

body: JSON.stringify({

114

socket_id: params.socketId,

115

channel_name: params.channelName,

116

user_id: getCurrentUserId()

117

})

118

})

119

.then(response => response.json())

120

.then(data => callback(null, data))

121

.catch(error => callback(error, null));

122

}

123

}

124

});

125

```

126

127

### User Authentication Options

128

129

Configuration for user authentication in presence channels.

130

131

```typescript { .api }

132

/**

133

* User authentication configuration

134

*/

135

interface UserAuthenticationOptions {

136

transport: 'ajax' | 'jsonp';

137

endpoint: string;

138

params?: any;

139

headers?: any;

140

paramsProvider?: () => any;

141

headersProvider?: () => any;

142

customHandler?: UserAuthenticationHandler;

143

}

144

145

/**

146

* User authentication request parameters

147

*/

148

interface UserAuthenticationRequestParams {

149

socketId: string;

150

}

151

152

/**

153

* User authentication response data

154

*/

155

interface UserAuthenticationData {

156

auth: string;

157

user_data: string;

158

}

159

160

/**

161

* User authentication callback function

162

*/

163

type UserAuthenticationCallback = (

164

error: Error | null,

165

authData: UserAuthenticationData | null

166

) => void;

167

168

/**

169

* Custom user authentication handler

170

*/

171

interface UserAuthenticationHandler {

172

(params: UserAuthenticationRequestParams, callback: UserAuthenticationCallback): void;

173

}

174

```

175

176

**User Authentication Examples:**

177

178

```typescript

179

// Basic user authentication

180

const pusher = new Pusher("app-key", {

181

cluster: "us2",

182

userAuthentication: {

183

endpoint: "/pusher/user-auth",

184

transport: "ajax"

185

}

186

});

187

188

// User authentication with custom data

189

const pusher = new Pusher("app-key", {

190

cluster: "us2",

191

userAuthentication: {

192

endpoint: "/api/pusher/user-auth",

193

transport: "ajax",

194

headers: {

195

"Authorization": "Bearer user-token"

196

},

197

params: {

198

user_id: "user-123"

199

}

200

}

201

});

202

203

// Custom user authentication handler

204

const pusher = new Pusher("app-key", {

205

cluster: "us2",

206

userAuthentication: {

207

endpoint: "/pusher/user-auth",

208

transport: "ajax",

209

customHandler: (params, callback) => {

210

const userData = {

211

id: getCurrentUserId(),

212

name: getCurrentUserName(),

213

avatar: getCurrentUserAvatar()

214

};

215

216

// Generate auth signature and user data

217

generateUserAuth(params.socketId, userData)

218

.then(authData => callback(null, authData))

219

.catch(error => callback(error, null));

220

}

221

}

222

});

223

224

// Sign in user for presence channels

225

pusher.signin();

226

```

227

228

### Deprecated Authorization (Backward Compatibility)

229

230

Legacy authorization options maintained for backward compatibility.

231

232

```typescript { .api }

233

/**

234

* Deprecated authorization options (for backward compatibility)

235

*/

236

interface DeprecatedAuthOptions {

237

params?: any;

238

headers?: any;

239

}

240

241

/**

242

* Deprecated channel authorizer interface

243

*/

244

interface DeprecatedChannelAuthorizer {

245

authorize(socketId: string, callback: ChannelAuthorizationCallback): void;

246

}

247

248

/**

249

* Deprecated authorizer generator function

250

*/

251

interface ChannelAuthorizerGenerator {

252

(channel: Channel, options: DeprecatedAuthorizerOptions): DeprecatedChannelAuthorizer;

253

}

254

255

interface DeprecatedAuthorizerOptions {

256

authTransport: 'ajax' | 'jsonp';

257

authEndpoint: string;

258

auth?: DeprecatedAuthOptions;

259

}

260

```

261

262

**Deprecated Authorization Examples:**

263

264

```typescript

265

// Legacy auth configuration (still supported)

266

const pusher = new Pusher("app-key", {

267

cluster: "us2",

268

authEndpoint: "/pusher/auth",

269

authTransport: "ajax",

270

auth: {

271

params: { user_id: "123" },

272

headers: { "X-CSRF-Token": "token" }

273

}

274

});

275

276

// Legacy custom authorizer

277

const pusher = new Pusher("app-key", {

278

cluster: "us2",

279

authEndpoint: "/pusher/auth",

280

authorizer: (channel, options) => {

281

return {

282

authorize: (socketId, callback) => {

283

// Custom authorization logic

284

customAuthRequest(socketId, channel.name, callback);

285

}

286

};

287

}

288

});

289

```

290

291

### Authentication Request Types

292

293

Enumeration of authentication request types.

294

295

```typescript { .api }

296

/**

297

* Authentication request type enumeration

298

*/

299

enum AuthRequestType {

300

UserAuthentication = "user-authentication",

301

ChannelAuthorization = "channel-authorization"

302

}

303

```

304

305

### Authentication Transport

306

307

Shared callback type for both channel and user authentication.

308

309

```typescript { .api }

310

/**

311

* Generic authentication transport callback

312

*/

313

type AuthTransportCallback = ChannelAuthorizationCallback | UserAuthenticationCallback;

314

315

/**

316

* Internal authentication options interface

317

*/

318

interface InternalAuthOptions {

319

transport: 'ajax' | 'jsonp';

320

endpoint: string;

321

params?: any;

322

headers?: any;

323

paramsProvider?: () => any;

324

headersProvider?: () => any;

325

}

326

```

327

328

## Authentication Flow Examples

329

330

### Private Channel Authentication

331

332

```typescript

333

// Server endpoint should return JSON like:

334

// { "auth": "app_key:signature" }

335

336

const pusher = new Pusher("app-key", {

337

cluster: "us2",

338

channelAuthorization: {

339

endpoint: "/pusher/auth",

340

transport: "ajax"

341

}

342

});

343

344

// Subscribe to private channel

345

const privateChannel = pusher.subscribe("private-user-messages");

346

347

privateChannel.bind("pusher:subscription_succeeded", () => {

348

console.log("Successfully authenticated and subscribed");

349

});

350

351

privateChannel.bind("pusher:subscription_error", (error) => {

352

console.error("Authentication failed:", error);

353

});

354

```

355

356

### Presence Channel Authentication

357

358

```typescript

359

// Server endpoint should return JSON like:

360

// {

361

// "auth": "app_key:signature",

362

// "channel_data": "{\"user_id\":\"123\",\"user_info\":{\"name\":\"Alice\"}}"

363

// }

364

365

const pusher = new Pusher("app-key", {

366

cluster: "us2",

367

channelAuthorization: {

368

endpoint: "/pusher/auth",

369

transport: "ajax",

370

headers: {

371

"Authorization": "Bearer user-token"

372

}

373

}

374

});

375

376

// Subscribe to presence channel

377

const presenceChannel = pusher.subscribe("presence-chat-room");

378

379

presenceChannel.bind("pusher:subscription_succeeded", (members) => {

380

console.log("Joined presence channel");

381

console.log("Current members:", members);

382

});

383

```

384

385

### User Authentication for Presence

386

387

```typescript

388

// Server endpoint should return JSON like:

389

// {

390

// "auth": "app_key:user_signature",

391

// "user_data": "{\"id\":\"123\",\"name\":\"Alice\",\"avatar\":\"url\"}"

392

// }

393

394

const pusher = new Pusher("app-key", {

395

cluster: "us2",

396

userAuthentication: {

397

endpoint: "/pusher/user-auth",

398

transport: "ajax"

399

}

400

});

401

402

// Sign in user (enables presence without channel_data)

403

pusher.signin();

404

405

// Now presence channels work without channel_data in auth response

406

const presenceChannel = pusher.subscribe("presence-general");

407

```

408

409

## Error Handling

410

411

### Authentication Errors

412

413

```typescript { .api }

414

/**

415

* HTTP authentication error

416

*/

417

class HTTPAuthError extends Error {

418

status: number;

419

constructor(status: number, msg?: string);

420

}

421

```

422

423

**Error Handling Examples:**

424

425

```typescript

426

// Handle authentication errors

427

pusher.bind("error", (error) => {

428

if (error instanceof HTTPAuthError) {

429

console.error(`Auth failed with status ${error.status}:`, error.message);

430

431

switch (error.status) {

432

case 401:

433

// Redirect to login

434

window.location.href = "/login";

435

break;

436

case 403:

437

// Show access denied message

438

showError("Access denied to this channel");

439

break;

440

default:

441

showError("Authentication error occurred");

442

}

443

}

444

});

445

446

// Channel-specific error handling

447

channel.bind("pusher:subscription_error", (error) => {

448

console.error("Channel subscription failed:", error);

449

// Handle channel-specific auth failure

450

});

451

```

452

453

## Server-Side Implementation Examples

454

455

### Express.js Channel Authorization

456

457

```javascript

458

// Example Express.js endpoint for channel authorization

459

app.post('/pusher/auth', express.json(), (req, res) => {

460

const { socket_id, channel_name } = req.body;

461

const user = authenticateUser(req); // Your auth logic

462

463

if (!user) {

464

return res.status(401).json({ error: 'Unauthorized' });

465

}

466

467

// For private channels

468

if (channel_name.startsWith('private-')) {

469

const auth = pusher.authenticate(socket_id, channel_name);

470

res.json(auth);

471

}

472

473

// For presence channels

474

else if (channel_name.startsWith('presence-')) {

475

const presenceData = {

476

user_id: user.id,

477

user_info: {

478

name: user.name,

479

avatar: user.avatar

480

}

481

};

482

483

const auth = pusher.authenticate(socket_id, channel_name, presenceData);

484

res.json(auth);

485

} else {

486

res.status(400).json({ error: 'Invalid channel' });

487

}

488

});

489

```

490

491

### User Authentication Endpoint

492

493

```javascript

494

// Example user authentication endpoint

495

app.post('/pusher/user-auth', express.json(), (req, res) => {

496

const { socket_id } = req.body;

497

const user = authenticateUser(req);

498

499

if (!user) {

500

return res.status(401).json({ error: 'Unauthorized' });

501

}

502

503

const userData = {

504

id: user.id,

505

name: user.name,

506

avatar: user.avatar,

507

role: user.role

508

};

509

510

const auth = pusher.authenticateUser(socket_id, userData);

511

res.json(auth);

512

});

513

```