Authentication
Public channels are open to anyone with your app key. For private and presence channels your own server decides who may subscribe, using a signature that only it can produce.
The flow
- A client subscribes to
private-room-1. - The client library sends
socket_idandchannel_nameto your authorization endpoint (a normal HTTP POST, with your session cookie). - Your server checks that this user may join that channel. If so, it answers with a signed token made with your app secret.
- The client hands that token to Vixus Push, which verifies the signature and lets the subscription through.
The secret never leaves your server, and a client without a valid token cannot join.
On the client
Tell pusher-js where your endpoint is:
js
const pusher = new Pusher("YOUR_APP_KEY", {
cluster: "",
wsHost: "YOUR_HOST",
wsPort: 443,
wssPort: 443,
forceTLS: true,
enabledTransports: ["ws", "wss"],
channelAuthorization: {
endpoint: "/api/pusher/auth",
transport: "ajax",
},
});
const channel = pusher.subscribe("private-room-1");The library POSTs socket_id and channel_name as form fields and sends cookies for same-site endpoints. Your host and port are on your app's Overview page, see Quickstart.
On the server
This is a complete Next.js route handler. The pattern is the same in any framework: check the user, then return what authorizeChannel gives you.
ts
import Pusher from "pusher";
const pusher = new Pusher({
appId: process.env.PUSHER_APP_ID!,
key: process.env.PUSHER_APP_KEY!,
secret: process.env.PUSHER_APP_SECRET!,
host: process.env.PUSHER_HOST!,
port: process.env.PUSHER_PORT!,
useTLS: true,
});
export async function POST(request: Request) {
const user = await getCurrentUser(request); // your own session check
if (!user) return new Response("Unauthorized", { status: 401 });
const form = await request.formData();
const socketId = String(form.get("socket_id"));
const channel = String(form.get("channel_name"));
// Your rule: may this user join this channel?
if (!(await canJoin(user, channel))) {
return new Response("Forbidden", { status: 403 });
}
return Response.json(pusher.authorizeChannel(socketId, channel));
}Presence channels
For presence channels pass the member's identity as a third argument. user_id is required and identifies the member; user_info is shown to everyone else on the channel, so only put in what they may see.
ts
return Response.json(
pusher.authorizeChannel(socketId, channel, {
user_id: String(user.id),
user_info: { name: user.name },
}),
);Laravel
Laravel does this for you. Register the broadcasting routes, define who may join in routes/channels.php, and Laravel Echo sends the requests, see the Laravel tab in the Quickstart.
User authentication
An app can also let a client sign in as a user (separate from joining channels). Switch on User authentication in your app's Settings, point the client at an endpoint with userAuthentication: { endpoint }, and answer it with pusher.authenticateUser(socketId, { id: "42" }). It applies to connections opened after you enable it. We run the underlying server's implementation but do not test it ourselves.