Authentication and Signatures

Vask uses Pusher-compatible signing for channel authorization, user authentication, webhooks, and HTTP API requests.

Use your Vask app_key anywhere a Pusher SDK asks for an app key. If a server SDK also asks for app_id, use the same app_key.

#Channel authorization

Private, presence, private cache, presence cache, encrypted, and encrypted cache channels require authorization.

The client SDK sends your application server:

socket_id=1234.5678
channel_name=private-dashboard.42

For private channels, sign this string with HMAC-SHA256 using the app secret:

1234.5678:private-dashboard.42

Return:

{
    "auth": "app_key:hmac_signature"
}

#Presence authorization

Presence channels add channel_data. The exact JSON string you return must be the exact JSON string you sign.

{
    "user_id": "user-123",
    "user_info": {
        "name": "Ada"
    }
}

Sign:

1234.5678:presence-room.42:{"user_id":"user-123","user_info":{"name":"Ada"}}

Return:

{
    "auth": "app_key:hmac_signature",
    "channel_data": "{\"user_id\":\"user-123\",\"user_info\":{\"name\":\"Ada\"}}"
}

#User authentication

User authentication identifies the connection itself. It powers server-to-user events, watchlist events, and user connection termination.

The auth endpoint signs:

1234.5678::user::{"id":"user-123","name":"Ada"}

Return:

{
    "auth": "app_key:hmac_signature",
    "user_data": "{\"id\":\"user-123\",\"name\":\"Ada\"}"
}

The client then sends pusher:signin over the WebSocket connection.

#HTTP API authentication

Every request to https://api.vask.dev/apps/{app_key}/... must be signed.

Required query parameters:

Parameter Description
auth_key Your Vask app_key.
auth_timestamp Unix timestamp in seconds.
auth_version Use 1.0.
body_md5 MD5 hex digest of the request body for non-empty POST bodies.
auth_signature HMAC-SHA256 hex digest of the string to sign.

String to sign:

METHOD
/apps/{app_key}/events
auth_key=app_key&auth_timestamp=1715520000&auth_version=1.0&body_md5=...

Node example:

import crypto from 'node:crypto';

function signRequest({ method, path, params, secret }) {
    const query = Object.keys(params)
        .sort()
        .map((key) => `${key}=${params[key]}`)
        .join('&');

    return crypto
        .createHmac('sha256', secret)
        .update(`${method.toUpperCase()}\n${path}\n${query}`)
        .digest('hex');
}

#Webhook signatures

Webhook deliveries use the app secret to sign the raw request body.

X-Pusher-Key: app_key
X-Pusher-Signature: hmac_sha256(raw_body, app_secret)

Do not parse and re-encode the body before verification.

#Common failures

Symptom Check
401 from HTTP API Wrong secret, stale timestamp, missing body_md5, or signed path differs from request path.
pusher:error on private subscribe Auth endpoint signed the wrong socket_id or channel_name.
Presence user missing channel_data was not included, not valid JSON, or did not include user_id.
User termination does nothing The target connection has not completed pusher:signin.

Prefer raw markdown? View this page as markdown.