Socket.io authentication with JWT - node.js

Recently I started learning socket.io at work and I got the general concept of emitting events and listening to events. Currently I'm building a simple chat app with Node.js, Express and Socket.io and I want to add authentication to my app, so that on page refresh, the data is saved and the connection is retained.
I read a lot about token-based authentication vs cookie based authentication and I understood that in most cases it's better to use token based authentication strategy.
I found a lot of npm packages regarding this topic that help authenticate requests but I can't find one simple way of implementation for simple authentication.
My question is: What is the best/correct way of implementing authentication with sockets?
If you guys could help me with this issue, I'd really appreciate it.

When the client connects to the server, make it a requirement to send an 'authentication' event to the server with the token, if the user doesn't send this event within 5 seconds then disconnect them, if the token is invalid then disconnect them, only allow them to stay connected if they have a valid access token.
Also ensure they send this token up each time they make a request to the server & validate it, not 100% necessary because they wouldn't have been able to connect in the first place without a valid token but it wouldn't hurt.

Related

NodeJS REST API

I'd like to understand how to make sure that only intended clients are connecting to API server?
For example there is an end point: http://example.com/v1/api/getallcustomers
Users will be authenticated
Token will be issued
Authentication will be done on every request
But I'd like to make sure only my Web and Mobile apps are connecting to this API. I would like to block/deny all other incoming connections even you know the end point. Please help. Thank you.
Cheers,
I'd like to make sure only my Web and Mobile apps are connecting to this API. I would like to block/deny all other incoming connections even you know the end point.
That is impossible since anyone who knows how the API works and has access to a valid authentication token can make a request (using Node.js, for example). You have no way of distinguishing a request made from your app from one made from some other program.

How to authenticate with Node.js/Express + Passport + Websockets?

I am building an angular2-login-seed that uses Passport.js with OAuth strategies for authentication. Obviously the default method of authentication with these tools is use of an HTTP cookie signed by express. Passport, from what I can tell, manages the actual Set Cookie header so that express can authenticate each subsequent request via request.isAuthenticated() and access the data set by passport via req.session.passport.dataHere.
I want to incorporate realtime data in the application via websockets. This of course means a socket stream coming from the server to the client. This communication is entirely separate from a regular HTTP server request meaning:
It does not contain the HTTP cookie that all HTTP requests contain
Express does not broker the interaction with sockets, it is managed with whatever implementation is used in the backend (sock.js, socket.io)
This makes it difficult to streamline authentication between HTTP requests to express, and websocket data to the backend as they are separate methods of communication.
From my research, this leaves me with two options. One of which is to use a library to give my socket implementation (preferably sock.js over socket.io but I need to do more research) access to the express session. Then I could authenticate the socket connection however I want. Issue is I have no idea how I would get the express cookie into the stream from the front since javascript cannot access it (HTTP only cookie).
Another common solution I've seen people jump to is to use JWTs (JSON Web Tokens). Implementations revolving around this store the JWT in localstorage on the front end. This is so the SPA (in my case Angular2 services) could send it with every request for 'stateless' server authentication AND we could send it via a websocket to authenticate the websocket connection as well (the front end JS has access to localstorage obviously). A couple things that come to mind when thinking about this implementation:
Is it even possible to have Passport OAuth strategies use JWT instead of the regular session information? What modification would this entail? From what I can tell the Passport strategies use some form of OAuth1 or OAuth2 parent strategies for authentication which defaults to using cookies.
Would storing this vital information in localstorage open the application up to security breaches (XSS, CSRF, etc)
If so, the most common workaround I've seen is to store the JWT in a cookie so it cannot be as easily accessed, spoofed, or forged. However this puts me back in the position I was in before using JWT, so might as well not bother.
Does this mean I'd have to use some sort of state management store in the backend (Redis for example) to manage the authentication and decoding of the JWT body? (I know nothing about Redis, etc).
The idea of connecting authentication between server HTTP requests and socket data is odd but seemingly vital to properly authenticating a socket connection. I'm a little surprised an easier method does not exist. I've done some research and have seen things such as socketio-jwt, express-jwt, etc however I don't know if this would be a manageable transition with my Passport strategies, or if it would be easier opening up express session data to the socket implementation, or if I'm going about it all wrong!
Any help or guidance would be much appreciated thanks.
Then I could authenticate the socket connection however I want. Issue is I have no idea how I would get the express cookie into the stream from the front since javascript cannot access it (HTTP only cookie).
With express-socket.io-session the session auth is done on handshake, and the handshake is a http request, so even if your cookies are http-only it will work. (Tested by myself)

Is this a sound authentication scheme for Node.js and Socket.io?

I am trying to setup a user login system with Node.js (Express), Socket.io, and Redux/ReactJS. This is the approach I'm taking:
The user connects through Socket.io as soon as he/she gets to the web app.
Through socketio-auth the user is required to authenticate and passes their username and password to the server.
Then, using socket.io-express-session, like in this example, I set a cookie with the user's username and password, so that every time they come back to the website they can be re-authenticated through socketio-auth. (I realize I could probably save a unique token in the cookie instead, would this be better?)
On the server, upon authentication, I just save their details with their socketId to the Redux store for use with every Socket.io request while the session lasts.
Assuming this is all done over SSL, is this safe? What changes would you suggest? I'm trying to make it as simple as possible yet still very safe.
It seems like point 3, with Local Storage, is the best way to go for now.
See someone else interrogation: https://github.com/hueniverse/hawk/issues/138#issuecomment-196989520

NodeJS and Socket.IO user authentication

I was wondering what are the best practices for socket.IO authentication.
Alice emits event 'message' with parameters including Bobs unique identifier etc. Bob receives the message while listening to socket.on('message') event.
How do I prevent unauthenticated users from ever connecting to the server using Socket.IO and how do I emit event to only specific user?
Thank you very much in advance for all suggestions and answers.
Peter
Socket.IO allows you to set up authentication for new sessions. You could do this with cookies or using JSON web tokens for example. The authentication mechanism did change from 0.9 to 1.0, so just be aware of that when googling.
As far as encryption goes, as long as you're using https you should be fine. Trying to implement your own encryption scheme instead of using https is more risky and more work anyway.

How can I authorise a client in an OAuth-esque way?

Let's say I have 2 servers (server and authenticator), and I have a client. My end goal here is to be able to identify the client on server. My solution was to come up with a token/secret system like OAuth: client has a token and secret. It passes it to server. Server passes it to authenticator. If valid, server allows the request.
Obviously, this is nonoptimal just for the number of requests being made. The reason authenticator and server are separated is because this is for a decentralised service-- any number of servers may be used, and it's impractical to ask client libraries to register on each server.
So, the question remains, what's the best/correct way to do this? The goal is to create a system that is decentralised, but can still have clients identify themselves in a relatively secure fashion to the server.
Disclaimer: I'm not a security expert so I could be off-base here and in actual implementation there seems to be a number of security issues that would need to be ironed out.
In the broadest sense, could you have the client supply credentials to the authenticator and then upon verification the authenticator supplies the client and the server both with matching security tokens and then the client and server can communicate directly?
Just curious about there a reason you don't want to implement OAuth and run your own OAuth server.
Additional reference: http://groups.google.com/group/37signals-api/msg/aeb0c8bf67a224cc
Turns out the solution was to define my problem a bit better. As I'm only trying to create a way to block applications, I only need to store their name and key when they request the server. Then, as long as they're not blocked and the key matches the one in the datastore, they'll be identified. So I'm not trying to authenticate so much as identify. Thanks for the input!

Resources