In this method for authentication I send my requests with an extra headers as follows:
$.post("/_api/socket/login",(data)=>{
console.log(data);
let apiToken=data.token;
const socket=io({extraHeaders:{token:apiToken},auth:{token:apiToken}});
});
With the first post request we get a token (It is done in express so we easily can get a token in the case of user is authenticated) and then I initialize my socket with an extraHeaders (I can't get auth in express middlewares! Altough I think it dont different because of nature of tokens). Then I add the following middlewares in my io Initialization in server:
socketGetToken:(req,res,next)=>{
if (req.isAuthenticated()) {
let user=req.user;
if (user) {
let signedToken=JWT.sign({
data:user._id,
exp:(new Date()).setMinutes((new Date()).getMinutes()+5)
},jwtSecret);
res.status(statusCodes.OK);
return res.json({
status:statusCodes.OK,
success:true,
token:signedToken
})
} else {
res.status(statusCodes.UNAUTHORIZED);
return res.json({
status:statusCodes.UNAUTHORIZED,
success:false,
message:"Couldn't Authenticate User!"
});
}
}
passport.authenticate("local",(err,user)=>{
if (user) {
let signedToken=JWT.sign({
data:user._id,
exp:(new Date()).setDate((new Date()).getDate()+1)
},jwtSecret);
res.status(statusCodes.OK);
return res.json({
status:statusCodes.OK,
success:true,
token:signedToken
})
} else {
res.status(statusCodes.UNAUTHORIZED);
return res.json({
status:statusCodes.UNAUTHORIZED,
success:false,
message:"Couldn't Authenticate User!"
});
}
})(req,res,next);
},
verifyJWTSocket:(req,res,next)=>{
console.log(req)
let jwt=req.headers.token;
if (!jwt) {
next(new Error("UnAuthorized!"));
}
JWT.verify(jwt,jwtSecret,(err,payload)=>{
if (!payload) {
next(new Error("UnAuthorized!"));
}
User.findById(payload.data)
.then(user=>{
// req.logIn(user,err=>{});//configure current user for using in API for example enrolment
req.user=user; //This is better in case of no session or cookie!
next();
})
.catch(err=>{
next(new Error(err.message));
})
})
},
const wrapper=middleware=>(client,next)=>middleware(client.request,{},next);
module.exports=(io)=>{
io.use(wrapper(userController.verifyJWTSocket));
io.use((client,next)=>{
if (client.request.user) {
next();
}
else {
next(new Error("UnAuthorized!"));
}
});
io.on("connection",client=>{
console.log(client.request.user)
console.log("Socket Connected");
});
}
As you can see we have current user too according the requestee of token and we can be assure that no one can don't fake itself instead of Others! (which is simply possible using hidden fields in html!)