Auth & Signatures
Complete HMAC-SHA256 signature algorithms for channels, user signin, and REST API.
Overview
Socketo utilizes standard HMAC-SHA256 signatures to authenticate channel subscriptions, client user sessions, and backend REST API requests.
1. Private Channel Authorization
Clients subscribing to private-* channels must submit an authorization token signed by the application backend.
String to sign: ${socket_id}:${channel_name}
Algorithm: HMAC-SHA256(secret, string_to_sign)
Response: { "auth": "${app_key}:${signature}" }2. Presence Channel Authorization
Subscriptions to presence-* channels include serialized user identity metadata in the signature calculation:
String to sign: ${socket_id}:${channel_name}:${channel_data}
Algorithm: HMAC-SHA256(secret, string_to_sign)
Response: { "auth": "${app_key}:${signature}", "channel_data": "${channel_data}" }channel_data must be a valid JSON string (e.g. JSON.stringify({ user_id: "...", user_info: { ... } })).
3. User Authentication (pusher:signin)
Connection-level user sign-in links an authenticated user identity to an active socket connection:
String to sign: ${socket_id}::user::${user_data}
Algorithm: HMAC-SHA256(secret, string_to_sign)
Response: { "auth": "${app_key}:${signature}", "user_data": "${user_data}" }user_data must be a valid JSON string (e.g. JSON.stringify({ id: "...", user_info: { ... } })).
4. REST API Request Signing
All HTTP requests to /apps/:id/* require query-string HMAC authentication.
Authentication Query Parameters
| Parameter | Type | Description |
|---|---|---|
auth_key | string | Public application key (app.id). |
auth_timestamp | number | Unix timestamp in seconds (valid within ±600 seconds of server time). |
auth_version | string | Must be exactly "1.0". |
body_md5 | string | Hex MD5 digest of the request body (required for POST, PUT, PATCH). |
auth_signature | string | Calculated HMAC-SHA256 signature. |
Canonical Signing Format
METHOD
PATH
QUERY_STRINGRules for QUERY_STRING:
- Exclude
auth_signature. - Convert all parameter keys to lowercase.
- Sort parameters lexicographically by key.
- Format as unescaped
key=valuepairs delimited by&.
TypeScript Reference Implementation
import crypto from 'node:crypto'
// 1. Private Channel Auth
export function signPrivateChannel(socketId: string, channel: string, key: string, secret: string) {
const toSign = `${socketId}:${channel}`
const signature = crypto.createHmac('sha256', secret).update(toSign).digest('hex')
return { auth: `${key}:${signature}` }
}
// 2. Presence Channel Auth
export function signPresenceChannel(socketId: string, channel: string, userData: object, key: string, secret: string) {
const channelData = JSON.stringify(userData)
const toSign = `${socketId}:${channel}:${channelData}`
const signature = crypto.createHmac('sha256', secret).update(toSign).digest('hex')
return { auth: `${key}:${signature}`, channel_data: channelData }
}
// 3. User Signin Auth
export function signUserAuth(socketId: string, userData: object, key: string, secret: string) {
const dataString = JSON.stringify(userData)
const toSign = `${socketId}::user::${dataString}`
const signature = crypto.createHmac('sha256', secret).update(toSign).digest('hex')
return { auth: `${key}:${signature}`, user_data: dataString }
}
// 4. REST API Signing
export function signRestRequest(
method: string,
path: string,
key: string,
secret: string,
body?: string,
extraParams: Record<string, string> = {},
) {
const params: Record<string, string> = {
auth_key: key,
auth_timestamp: String(Math.floor(Date.now() / 1000)),
auth_version: '1.0',
...extraParams,
}
if (body && ['POST', 'PUT', 'PATCH'].includes(method.toUpperCase())) {
params.body_md5 = crypto.createHash('md5').update(body).digest('hex')
}
const sortedQuery = Object.keys(params)
.map((k) => [k.toLowerCase(), params[k]])
.sort(([a], [b]) => a.localeCompare(b))
.map(([k, v]) => `${k}=${v}`)
.join('&')
const toSign = `${method.toUpperCase()}\n${path}\n${sortedQuery}`
const signature = crypto.createHmac('sha256', secret).update(toSign).digest('hex')
return `${sortedQuery}&auth_signature=${signature}`
}