Presence channel authorization
Presence channels add a channel_data payload that becomes the public profile every other subscriber sees. Your auth endpoint includes it alongside the signature.
Shape
{
"auth": "YOUR_KEY:hex_hmac_sha256",
"channel_data": "{\"user_id\":\"42\",\"user_info\":{\"name\":\"Alice\"}}"
}channel_data is a JSON-encoded string (yes, a string, even though it contains JSON — Pusher’s protocol).
The user_id must be unique per user; user_info is whatever public data you want subscribers to see (name, avatar URL, etc.). Don’t put secrets in here — it’s broadcast to every other member.
Laravel
routes/channels.php:
Broadcast::channel('room.{id}', function ($user, $id) {
return [
'id' => $user->id, // becomes user_id
'name' => $user->name,
'avatar' => $user->avatar_url,
];
});Returning an array signals “this is a presence channel.” Returning true would have made it private.
Node.js
const presence = {
user_id: String(req.session.userId),
user_info: {
name: req.session.name,
avatar: req.session.avatar,
},
};
const auth = pusher.authorizeChannel(socket_id, channel_name, presence);
res.json(auth);PHP
$auth = $pusher->authorizePresenceChannel(
$_POST['channel_name'],
$_POST['socket_id'],
(string) $userId,
[
'name' => $user->name,
'avatar' => $user->avatar_url,
],
);
header('Content-Type: application/json');
echo $auth;Python
auth = p.authenticate(
channel=channel,
socket_id=socket_id,
custom_data={
'user_id': str(user_id),
'user_info': {
'name': user.name,
'avatar': user.avatar_url,
},
},
)
return jsonify(auth)Tips
- The total
channel_datapayload is capped at 10 KB. Keepuser_infosmall. - The same
user_idcan have multiple connected sockets (open in many tabs). Mawjly counts them as one member with multiple subscriptions —user_countandsubscription_countdiffer. member_addedonly fires when a brand-newuser_idjoins; second tab from the same user is silent.