Situation
I'm using the framework MEAN.JS in my app:
For the chat of this app I'm using the Real-Time SocketIO library:
- Socket.IO
v.1.3.5
(Server: NodeJS) - Angular-Socket-IO
v.0.7
(Client: AngularJS)
In this app, there are 2 ways to Sign In:
Local: After the sign in, the server returns the user object.
Another social network
OAuth 2.0
: After the sign in, the server redirects to home page/#!/
.
I'm using too:
- JWT-Simple
v.0.3.0
(JSON Web Token library)
What I want?
- I want to authenticate the users in SocketIO for the Chat, via JSON Web
Token
JWT
.
1rst
In the server, first, we need to encode the JSON object of the user with JWT
, and return the TOKEN
to the Client...
(no code for this)
Perhaps something like this:
var tokenSecret = '15b949c87eba2e8c949db9512acb401d';
var token = jwt.encode(req.user, tokenSecret);
res.jsonp(token);
2nd
The Client sends the same accessToken to the server, in the SocketIO connection
Client: socket-io.client.factory.js
(function() {
'use strict';
angular
.module('core')
.factory('Socket', Socket);
Socket.$inject = ['socketFactory'];
function Socket(socketFactory) {
var accessToken = //???
return socketFactory({
prefix: '',
ioSocket: io.connect('http://localhost:8080',{query:{accessToken:accessToken}})
});
}
})();
3th
The server decode the Token for checking that is the same user, and save the userId inside the Socket, and when is connected, join the user to the chat.
Server: express.js
// Attach Socket.io
var tokenSecret = '15b949c87eba2e8c949db9512acb401d';
var server = http.createServer(app);
var io = socketio.listen(server);
io.use(function(socket, next) {
var handshake = socket.request;
var decoded;
try {
decoded = jwt.decode(handshake.query().accessToken, tokenSecret);
} catch (err) {
console.error(err);
next(new Error('Invalid token!'));
}
if (decoded) {
// everything went fine - save userId as property of given connection instance
socket.userId = decoded.userId; // save user id we just got from the token, to be used later
next();
} else {
// invalid token - terminate the connection
next(new Error('Invalid token!'));
}
});
io.on('connection', function(socket){
socket.join(socket.userId);
io.on('disconnect', function(){
socket.leave(socket.userId);
});
});
Questions
I have questions in the 1rst part.
In my first idea, the token generated by JWT
was sended to the client inside the user object after the sign in. But if the client sign in via OAuth 2.0
, this solution doesn't work because the server is redirecting the page to homepage and don't return any json. I was thinking to generate a route API that returns this token, and do a REST petition to get the token...
My second idea is that the server saves the token in MongoDB (schema of the user). And always we can get access to the token in easy way. In angularJS we have the variable Authentication.user
with the user data and don't need to generate a new route API.
My question is...
What is the best way to send the token generated by
JWT
from the server to the client? (Easy way and with more security)
Thank you!
Similar questions:
- MEANJS: Security in SocketIO
- Socket authentication with node.js & socket.io (using DaftMonk's generator-angular-fullstack)
- decode jwt token - is it secure?