Socket.IO Authentication and Authorization
handshake auth, JWT verify middleware, namespace auth ও authorization — বাংলায়।
Socket শুধু HTTP এর মতো নয় — connection দীর্ঘস্থায়ী। তাই token যাচাই সাধারণত handshake-এর সময় একবার করে middleware-এ, আর অনুমতি (authorization) প্রতিটি action-এ যাচাই করতে হয়।
শেখার লক্ষ্য
- client থেকে handshake auth পাঠানো
- server middleware-এ token যাচাই
- JWT ভিত্তিক auth বাস্তবায়ন
- authorization ভুল ধরার নিয়ম
Step 1: Client-এ Token পাঠানো
io()-এর auth option বা socket.auth-এ token দিন:
import { io } from "socket.io-client";
const token = localStorage.getItem("access_token");
const socket = io("http://localhost:3000", {
auth: { token },
});
// token পরিবর্তন হলে
socket.auth = { token: newToken };
socket.disconnect().connect();Step 2: Server Middleware
io.use() দিয়ে handshake পর্যায়ে token verify করুন। সমস্যা থাকলে next(err) — connection প্রতিষ্ঠিত হবে না।
import jwt from "jsonwebtoken";
io.use((socket, next) => {
const token = socket.handshake.auth.token;
if (!token) {
return next(new Error("token প্রয়োজন"));
}
try {
const payload = jwt.verify(token, process.env.JWT_SECRET);
// পরবর্তীতে ব্যবহারের জন্য socket-এ রাখুন
socket.data.user = { id: payload.sub, role: payload.role };
next();
} catch (err) {
next(new Error("token অবৈধ"));
}
});// client-এ ব্যর্থ auth
socket.on("connect_error", (err) => {
console.log(err.message); // "token অবৈধ"
});socket.handshake.auth কেবল handshake প্যাকেটে যায় — query string-এর মতো URL log-এ পড়ে না। তাই token আকারে headers/auth ব্যবহার করা নিরাপদ। মনে রাখবেন: connection দীর্ঘস্থায়ী হওয়ায় একবার verify করা token পরেও expire হতে পারে — sensitive action-এ আবার check করুন বা reconnection-এ re-auth ধরে নিন।
Namespace-Specific Auth
const verifyToken = (socket, next) => {
const token = socket.handshake.auth.token;
try {
const payload = jwt.verify(token, process.env.JWT_SECRET);
socket.data.user = { id: payload.sub, role: payload.role };
next();
} catch {
next(new Error("token অবৈধ"));
}
};
// root namespace
io.use(verifyToken);
// /admin namespace — এখানে root middleware চলে না, তাই আলাদা register
const adminNs = io.of("/admin");
adminNs.use(verifyToken);
adminNs.use((socket, next) => {
if (socket.data.user?.role === "admin") return next();
next(new Error("admin access required"));
});Authorization: প্রতিটি Action-এ
Authentication (কে আপনি) ঠিক হলে Authorization (আপনি কী করতে পারবেন) আলাদা করে:
socket.on("room:delete", async ({ roomId }, ack) => {
const user = socket.data.user;
// ownership check
const room = await db.room.findById(roomId);
if (!room) return ack({ ok: false, error: "not found" });
if (room.ownerId !== user.id && user.role !== "admin") {
return ack({ ok: false, error: "অনুমতি নেই" });
}
await db.room.delete(roomId);
io.to("room:" + roomId).emit("room:closed", roomId);
ack({ ok: true });
});Line-by-line
socket.handshake.auth.token— client-এর পাঠানো tokenjwt.verify(...)— signature ও expiry যাচাইsocket.data.user = {...}— যাচাই-করা user তথ্য রাখা (পরের handler-এ পাওয়া যায়)next()— অনুমোদন;next(err)— প্রত্যাখ্যান- Handler-এ আবার permission check — কেবল "logged in" থাকলেই সব allowed নয়
সাধারণ ভুল ও সমাধান
- Middleware না দিয়ে client data বিশ্বাস — যেকোনো user সব করতে পারবে
socket.data-তে যা খুশি রাখা — এখানে সংবেদনশীল গোপন তথ্য রাখবেন না; প্রয়োজনীয় minimum রাখুন- token URL query-তে পাঠানো — logs/proxies-এ leak হয়;
authব্যবহার করুন - role client থেকে পাঠানো —
{ role: "admin" }client-এর দাবি; server-এ verified token থেকে নিন
Practice Task
- লোকাল JWT বানিয়ে handshake auth-এ পাঠান; সঠিক/ভুল token test করুন
/adminnamespace-এ role ভিত্তিক middleware যোগ করুন- room owner ছাড়া delete আটকে authorization implement করুন
সম্পর্কিত অধ্যায়: Middleware · Namespaces · Best Practices