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

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)

Related

Is using JWT Tokens actually a secure way to work around user sessions?

I am trying to build a registration/login system using the PERN stack (Postgres, Express, React & Node) for a client website.
I was doing some researching and came across HTTP Cookie and JWT token authorizations (many more but apparently those two are the dominant).
I noticed alot apps and tutorials that uses Node JS seems to use JWT alot, and store these in localstorage. But I'm doubtful about the security because I feel like a developer can basically go into localstorage and get the JWT token which o
Is there a better way to secure user authentications with this stack or is using localstorage the rule of thumb? If so, why is that?
Thank you for your time.
One limiting medium to the security of both session IDs and JWTs is network transmission. In this case, both are only as secure as the network itself. But most likely, your application would be using something like HTTPS or SSL, in which case any data being sent across the network would be reasonably secure.
Regarding your other edge case of someone trying to sniff at a JWT in local storage, there are a few options you may consider:
First, the nature of the JWT is that it is generally tamper-proof. A JWT contains inside of it a checksum, which is a unique hash based on the actual contents of the JWT. Let's says that some malicious user sniffed local storage, and then tried to change e.g. the claims section of the JWT. In doing so, this would also change the checksum (which that user would not be able to figure out, lacking the server key). Then, the next time the compromised JWT is sent to the server, the server would reject it, because the computed checksum would not match with the value contained in the JWT.
Second, in the event the above be deemed not secure enough, it is possible to pass around encrypted JWT. If you go with this option, both the server and client would encrypt/decrypt before sending a JWT, which adds an extra layer of protection.
Security of network transmission is just one case of whole solution in web applications.
Im currently in the research of the same topic and as you said a lot of tutorials, blogs, youtube and other sources gives an excellent examples of using JWT tokens for handling user data. Unfortunately hardly anyone go deepest in handling and processing user sessions from administration point of view - where the real problems starts.
Logging the user in and sends JTW token in response to the client is not a problem at all. The problem begin when you as administrator want to invalidate a user.
Refer to this sources:
http://cryto.net/~joepie91/blog/2016/06/13/stop-using-jwt-for-sessions/
Logout/invalidate a JWT
The session cookie with session data stored in server-side is currently the best option for web application.

Storing Express session Id in React

I'm having a problem of understanding the steps for authentication using Express session(backend) + React(frontend)..
When a user logs in the server set up a session cookie object with the user id and this way it can identify if the user is logged in or not...
What about the client side? when user logs in and and I generate a token I send it back to the react app and save it in localStorage to use it for every request I make later? I heard that this is not secured.... So I ask you how should I implement that? How can I save the token I get from the server to use it when I make requests later?
One way I can think of is making another get request on server side which returns the session.userId so I can see if thats true then the user is logged in... I'm just trying to figure out how to implement that
thanks!
Browsers implement cookie storage, you don't have to do anything explicit on the client side to maintain the express session. When authentication first happens the server sends a header to the client instructing it to store a cookie and the browser will hold onto that cookie and send it back on all subsequent requests. None of this needs to happen in client scripts (i.e. your javascript code).
You don't need to store cookies in local storage, usually you should not and session cookies will be "httponly", meaning the client scripts are forbidden from accessing them. This is to mitigate the possibility of session stealing in the case of XSS.

Socket.io authentication with JWT

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.

are nodejs https 3rd party api requests encrypted?

I'm sorry if this is a daft question.
I'm developing an application that uses oauth2 to integrate with a 3rd party api via a server-side flow in node.
The one thing I'd like to confirm is that when I make the final post request to the 3rd party api to retrieve the access token using the node https module is whether or not the connection is encrypted.
From what I gather, when an https request is made from a browser, the browser handles encrypting the data on the client side. Does node encrypt the data in a similar way, or is this something that I need to implement myself?
If there is some background info that I've somehow overlooked in this regard, please let me know.
Thanks
To answer your question: if the OAuth API service you're querying is served over HTTPS, then your HTTP library (most likely request) is already handling encryption transparently for you. Any time you make a request to an HTTPS endpoint, your request WILL FAIL if the client is not handling encryption properly.

Node.js unit testing for session-specific middleware

I'm writing a unit test for a middleware that relies on persistent sessions in connect. (namely connect-mongo).
I'd like to create a fake session, but can't seem to figure out how.
I have a connect.sid cookie in my browser that I assume correlates to the _id in my sessions collection in some encrypted manner.
Here's what I tried:
I added in the cookieParser middleware and a session store to a server, then used the following request to send it up to the server (copied the key from chrome's dev tools panel):
var jar = request.jar(),
cookie = request.cookie('connect.sid=<REALLYLONGKEY>');
jar.add(cookie);
request({url : 'http://localhost:8585/',jar : jar},this.callback);
that correctly set the cookie on the server side, and I have verified that sessions are working.
However, the magic conversion from cookie to session didn't happen as I had hoped - what's the correct way to do this?
Setting the cookie on the server would only work if a session with that ID exists. Who created the session in the first place?
I can tell you what I did on my server. I wanted to create tests that simulate the client side and send requests to the server. I needed a way to authenticate the clients. My server allowed authentication based on Google OAuth. However, I did not want to go through the trouble of teaching the clients to sign into a Google account.
My solution was to implement an alternative method for signing in to my server - using nothing but a username. This feature is only enabled during testing and disabled for production. My test clients can now sign in without a problem. They receive the cookie 'connect.sid' as a result of the sign-in and send it back to the server in subsequent requests.
I too used request.jar() to create a cookie jar for my requests. I should note, however, that this is only necessary if you are simulating more than one client at the same time and need a separate cookie jar for each client.

Resources