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
```