Skip to content

Authentication overview

Jetsocket.io provides several authentication mechanisms to secure your real-time applications and protect sensitive data.

Channel authorization is used for private and presence channels. It ensures that only authorized users can subscribe to specific channels.

// Client-side
const channel = jetsocket.subscribe("private-my-channel");
// Server-side authorization endpoint
app.post("/jetsocket/auth", (req, res) => {
const socketId = req.body.socket_id;
const channel = req.body.channel_name;
if (canAccessChannel(req.user, channel)) {
const authResponse = jetsocket.authorizeChannel(socketId, channel);
res.send(authResponse);
} else {
res.status(403).send("Forbidden");
}
});

User authentication allows you to identify users across all their connections and send them targeted messages.

// Client-side
jetsocket.signin();
// Server-side authentication endpoint
app.post("/jetsocket/user-auth", (req, res) => {
const socketId = req.body.socket_id;
const user = req.user;
const authResponse = jetsocket.authenticateUser(socketId, {
user_id: user.id,
user_info: {
name: user.name,
email: user.email
}
});
res.send(authResponse);
});

All connections to Jetsocket.io are encrypted using TLS by default. This ensures that all data transmitted between your application and Jetsocket.io is secure.

const jetsocket = new Jetsocket("APP_KEY", {
cluster: "APP_CLUSTER",
forceTLS: true, // Default: true
});

For additional security, you can use encrypted channels that provide end-to-end encryption for sensitive data.

// Client-side
const channel = jetsocket.subscribe("private-encrypted-my-channel");
// Server-side (requires encryption master key)
const jetsocket = new Jetsocket({
appId: "APP_ID",
key: "APP_KEY",
secret: "APP_SECRET",
cluster: "APP_CLUSTER",
encryptionMasterKey: "your-encryption-key"
});

Webhooks are automatically verified to ensure they come from Jetsocket.io and haven’t been tampered with.

app.post("/jetsocket/webhook", (req, res) => {
const webhook = jetsocket.webhook(req);
if (webhook.isValid()) {
// Process webhook events
res.status(200).send("OK");
} else {
res.status(400).send("Invalid webhook");
}
});
// Good: Always verify user identity
app.post("/jetsocket/auth", authenticateUser, (req, res) => {
const user = req.user;
const channel = req.body.channel_name;
if (canAccessChannel(user, channel)) {
const authResponse = jetsocket.authorizeChannel(req.body.socket_id, channel);
res.send(authResponse);
} else {
res.status(403).send("Forbidden");
}
});
// Bad: No authentication
app.post("/jetsocket/auth", (req, res) => {
const authResponse = jetsocket.authorizeChannel(req.body.socket_id, req.body.channel_name);
res.send(authResponse);
});
function canAccessChannel(user, channel) {
// Validate channel name format
if (!channel || typeof channel !== 'string') {
return false;
}
// Check for private channel prefix
if (channel.startsWith('private-')) {
// Extract user ID from channel name
const userId = channel.replace('private-user-', '');
return user.id === userId;
}
return false;
}

Always use HTTPS for your authorization endpoints:

// Good: HTTPS endpoint
const jetsocket = new Jetsocket("APP_KEY", {
cluster: "APP_CLUSTER",
channelAuthorization: {
endpoint: "https://yourdomain.com/jetsocket/auth"
}
});
// Bad: HTTP endpoint (insecure)
const jetsocket = new Jetsocket("APP_KEY", {
cluster: "APP_CLUSTER",
channelAuthorization: {
endpoint: "http://yourdomain.com/jetsocket/auth"
}
});
const rateLimit = require("express-rate-limit");
const authLimiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15 minutes
max: 100 // limit each IP to 100 requests per windowMs
});
app.post("/jetsocket/auth", authLimiter, authenticateUser, (req, res) => {
// Authorization logic
});
app.post("/jetsocket/auth", authenticateUser, (req, res) => {
const user = req.user;
const channel = req.body.channel_name;
const socketId = req.body.socket_id;
console.log(`Auth attempt: User ${user.id} requesting access to ${channel}`);
if (canAccessChannel(user, channel)) {
console.log(`Auth success: User ${user.id} granted access to ${channel}`);
const authResponse = jetsocket.authorizeChannel(socketId, channel);
res.send(authResponse);
} else {
console.log(`Auth failed: User ${user.id} denied access to ${channel}`);
res.status(403).send("Forbidden");
}
});
// Create a channel for each user
const userId = getCurrentUserId();
const channel = jetsocket.subscribe(`private-user-${userId}`);
// Server-side authorization
function canAccessChannel(user, channel) {
if (channel.startsWith('private-user-')) {
const channelUserId = channel.replace('private-user-', '');
return user.id === channelUserId;
}
return false;
}
function canAccessChannel(user, channel) {
if (channel === 'private-admin-dashboard') {
return user.role === 'admin';
}
if (channel === 'private-moderator-chat') {
return user.role === 'admin' || user.role === 'moderator';
}
return false;
}
function canAccessChannel(user, channel) {
if (channel.startsWith('private-group-')) {
const groupId = channel.replace('private-group-', '');
return user.groups.includes(groupId);
}
return false;
}
const channel = jetsocket.subscribe("private-my-channel");
channel.bind("jetsocket:subscription_error", (error) => {
console.error("Authorization failed:", error);
if (error.status === 403) {
// Handle access denied
showMessage("You don't have permission to access this channel");
} else if (error.status === 401) {
// Handle authentication required
redirectToLogin();
} else {
// Handle other errors
showMessage("Failed to connect to channel");
}
});
app.post("/jetsocket/auth", async (req, res) => {
try {
const user = await authenticateUser(req);
const channel = req.body.channel_name;
if (canAccessChannel(user, channel)) {
const authResponse = jetsocket.authorizeChannel(req.body.socket_id, channel);
res.send(authResponse);
} else {
res.status(403).send("Forbidden");
}
} catch (error) {
console.error("Auth error:", error);
res.status(500).send("Internal server error");
}
});