Skip to content

Encrypted channels

Encrypted channels provide end-to-end encryption for sensitive data. Only authorized clients can decrypt the messages, ensuring that your data remains secure even from Jetsocket.io itself.

Encrypted channels are identified by the private-encrypted- prefix:

const jetsocket = new Jetsocket("APP_KEY", {
cluster: "APP_CLUSTER",
channelAuthorization: {
endpoint: "/jetsocket/auth"
}
});
const encryptedChannel = jetsocket.subscribe("private-encrypted-my-channel");

You need to configure the encryption master key on your server:

const Jetsocket = require("jetsocket");
const jetsocket = new Jetsocket({
appId: "APP_ID",
key: "APP_KEY",
secret: "APP_SECRET",
cluster: "APP_CLUSTER",
encryptionMasterKey: "your-32-character-encryption-key"
});

The encryption master key must be:

  • 32 characters long (256 bits)
  • Consistent across all servers that need to encrypt/decrypt messages
  • Secure - generate it randomly and keep it secret
const crypto = require("crypto");
// Generate a random 32-character key
const encryptionKey = crypto.randomBytes(32).toString("base64");
console.log("Encryption key:", encryptionKey);

Encrypted channels require the same authorization as private channels:

app.post("/jetsocket/auth", (req, res) => {
const socketId = req.body.socket_id;
const channel = req.body.channel_name;
const user = req.user;
if (canAccessChannel(user, channel)) {
const authResponse = jetsocket.authorizeChannel(socketId, channel);
res.send(authResponse);
} else {
res.status(403).send("Forbidden");
}
});
function canAccessChannel(user, channel) {
// Allow access to encrypted channels
if (channel.startsWith("private-encrypted-")) {
// Add your authorization logic here
return user.hasPermission("encrypted-channels");
}
return false;
}
// Trigger an encrypted event
jetsocket.trigger("private-encrypted-my-channel", "my-event", {
message: "This message is encrypted",
timestamp: new Date().toISOString()
});
const encryptedChannel = jetsocket.subscribe("private-encrypted-my-channel");
encryptedChannel.bind("my-event", (data) => {
console.log("Received encrypted message:", data);
// The message is automatically decrypted
});
<!DOCTYPE html>
<html>
<head>
<script src="https://js.jetsocket.io/latest/jetsocket-with-encryption.min.js"></script>
</head>
<body>
<div id="chat-container">
<h2>Secure Chat</h2>
<div id="messages"></div>
<input type="text" id="message-input" placeholder="Type a secure message...">
<button onclick="sendMessage()">Send</button>
</div>
<script>
const jetsocket = new Jetsocket("APP_KEY", {
cluster: "APP_CLUSTER",
channelAuthorization: {
endpoint: "/jetsocket/auth"
}
});
const encryptedChannel = jetsocket.subscribe("private-encrypted-secure-chat");
const messagesDiv = document.getElementById("messages");
// Handle successful subscription
encryptedChannel.bind("jetsocket:subscription_succeeded", () => {
console.log("Connected to encrypted channel");
addSystemMessage("Connected to secure chat");
});
// Handle subscription errors
encryptedChannel.bind("jetsocket:subscription_error", (error) => {
console.error("Failed to connect to encrypted channel:", error);
addSystemMessage("Failed to connect to secure chat");
});
// Handle encrypted messages
encryptedChannel.bind("new-message", (data) => {
addMessage(data);
});
function addMessage(data) {
const messageDiv = document.createElement("div");
messageDiv.className = "message";
messageDiv.innerHTML = `
<strong>${data.username}:</strong> ${data.message}
<small>${new Date(data.timestamp).toLocaleTimeString()}</small>
`;
messagesDiv.appendChild(messageDiv);
messagesDiv.scrollTop = messagesDiv.scrollHeight;
}
function addSystemMessage(message) {
const messageDiv = document.createElement("div");
messageDiv.className = "system-message";
messageDiv.textContent = message;
messagesDiv.appendChild(messageDiv);
messagesDiv.scrollTop = messagesDiv.scrollHeight;
}
function sendMessage() {
const input = document.getElementById("message-input");
const message = input.value.trim();
if (message) {
// Send to server via AJAX
fetch("/send-encrypted-message", {
method: "POST",
headers: {
"Content-Type": "application/json",
"Authorization": `Bearer ${getAuthToken()}`
},
body: JSON.stringify({
message: message,
channel: "private-encrypted-secure-chat"
})
});
input.value = "";
}
}
</script>
</body>
</html>
const express = require("express");
const Jetsocket = require("jetsocket");
const crypto = require("crypto");
const app = express();
app.use(express.json());
// Your encryption master key (store this securely!)
const ENCRYPTION_MASTER_KEY = process.env.ENCRYPTION_MASTER_KEY ||
crypto.randomBytes(32).toString("base64");
const jetsocket = new Jetsocket({
appId: "APP_ID",
key: "APP_KEY",
secret: "APP_SECRET",
cluster: "APP_CLUSTER",
encryptionMasterKey: ENCRYPTION_MASTER_KEY
});
// Authorization endpoint
app.post("/jetsocket/auth", authenticateUser, (req, res) => {
const socketId = req.body.socket_id;
const channel = req.body.channel_name;
const user = req.user;
if (canAccessChannel(user, channel)) {
const authResponse = jetsocket.authorizeChannel(socketId, channel);
res.send(authResponse);
} else {
res.status(403).send("Forbidden");
}
});
// Send encrypted message
app.post("/send-encrypted-message", authenticateUser, async (req, res) => {
try {
const { message, channel } = req.body;
const user = req.user;
// Validate channel is encrypted
if (!channel.startsWith("private-encrypted-")) {
return res.status(400).json({ error: "Invalid channel type" });
}
// Trigger encrypted event
await jetsocket.trigger(channel, "new-message", {
user_id: user.id,
username: user.username,
message: message,
timestamp: new Date().toISOString()
});
res.json({ success: true });
} catch (error) {
console.error("Error sending encrypted message:", error);
res.status(500).json({ error: "Failed to send message" });
}
});
function canAccessChannel(user, channel) {
if (channel.startsWith("private-encrypted-")) {
// Add your authorization logic here
return user.role === "admin" || user.hasPermission("encrypted-channels");
}
return false;
}
function authenticateUser(req, res, next) {
// Your authentication logic here
const token = req.headers.authorization?.split(" ")[1];
if (token) {
// Verify token and set req.user
req.user = verifyToken(token);
next();
} else {
res.status(401).send("Unauthorized");
}
}
app.listen(3000);
  • Store keys securely: Use environment variables or secure key management systems
  • Rotate keys regularly: Change encryption keys periodically
  • Backup keys safely: Ensure you can recover keys if needed
  • Limit key access: Only authorized personnel should have access to encryption keys
  • Use descriptive names: Make channel names indicate their purpose
  • Include organization prefix: Use prefixes like private-encrypted-org- for clarity
  • Avoid sensitive information: Don’t include sensitive data in channel names
// Good channel names
"private-encrypted-financial-data"
"private-encrypted-medical-records"
"private-encrypted-legal-documents"
// Bad channel names
"private-encrypted-secret-stuff"
"private-encrypted-12345"
encryptedChannel.bind("jetsocket:subscription_error", (error) => {
console.error("Encrypted channel error:", error);
if (error.status === 403) {
showMessage("Access denied to encrypted channel");
} else if (error.status === 500) {
showMessage("Encryption error - please try again");
} else {
showMessage("Failed to connect to encrypted channel");
}
});

Encrypted channels require additional encryption libraries, which increase the bundle size:

// Standard build (smaller)
import Jetsocket from 'jetsocket-js';
// Encryption-enabled build (larger)
import Jetsocket from 'jetsocket-js/with-encryption';
  • Encryption/decryption: Adds computational overhead
  • Key management: Requires additional processing
  • Network latency: Minimal impact on message delivery

Encrypted channels are perfect for:

  • Financial applications: Banking, payments, trading
  • Healthcare systems: Medical records, patient data
  • Legal applications: Confidential documents, attorney-client communications
  • Government systems: Classified information, secure communications
  • Enterprise applications: Sensitive business data, trade secrets
  • Test encryption: Verify encryption/decryption works correctly
  • Handle key rotation: Plan for key changes
  • Monitor performance: Watch for encryption-related performance issues
  • Log appropriately: Don’t log encrypted data
  • Use strong keys: Generate cryptographically secure keys
  • Secure key storage: Use secure key management systems
  • Monitor usage: Track encrypted channel usage
  • Plan for recovery: Have procedures for key recovery