A different way to manage sessions - node.js

I'm working in a cookie-less way to manage sessions in my project (expressjs), keeping all session data server side and using a token at client side (previously generated by the server) to validate the session on every request.
A new token will be created on user login and kept hide somewhere in the page, then, on every request this token will be written to the request header and validated server side. at this point server will search for the token in a session store, lets say redis, and get the session data if the token is found or respond with a message of session expired otherwise.
There are some things i'm considering for this:
Redis keys are created on user login with a settled expiration.
Every time session data is found in redis i have to 'touch' the key
so expiration time gets postponed.
Token will be validated along side with the ip address of the client so can't be used by other person.
My question is if this is can be considered a secure way to work with, and if there is anything i'm missing here. Thanks

OK, cookies are required for storing session. Express does it the ideal way.
In express session(not cookiesession) it is completely stored at the server, only a key is sent to the client. The whole session is serialized to a key which is then sent. I assume you want that user cannot tamper with the session cookies. You can use httponly cookies to prevent tampering. They are only handled by browser and cannot be accessed by user. This prevents cookie theft or session hijacking. You can enable httponly cookies with:
app.use(express.session({cookie: { path: '/', httpOnly: true}, secret:'password'}));
Still you should use some encryption to prevent eavesdropping of cookies. Use secure : true for that. You can also mention where you want to store the session with redis, mongo or simply in memory.
The request token validation that you mention is a technique commonly used to prevent Cross-site request forgery. It keeps changing the token dynamically to keep user from getting the token. You can use this in express with csrf middleware.
app.use(express.csrf())
IP matching will not work as IP of user can change over time.

Related

Token rotation refresh implementation how to persist token?

I have implemented all of the code to support token rotation/ refresh with one last hitch. How are we supposed to persist the token on the frontend to make authenticated backend calls beyond our login?
My Current workflow goes as follows:
User logs in with email and password and is returned the refresh token and the access token in an HTTP-only secure cookie.
A MongoDB (body) document along with the refresh Token and Access Token in HTTP-only, secure cookies is returned with the response.
Now moving on from here how can we persist using these cookies? Especially since we cannot access these. I am using HTTP-only cookies as that is what is recommended as it is most secure but I am struggling to see how it is possible with only HTTP cookies.
In case anyone stumbles across this. HTTP cookies persist by default. They were not persisting in my case as I had the secure property set to true and I was not over an https connection.

Best approach for maintaining sessions for logged in user . Which approach is the most efficient

While implementing authentication, what is the best approach to maintain session. So, I wanna know the best approach between the below:
Session-based Authentication: Server creates a session after user logged in and store the session in the DB with TTL (Example: 10 minutes) for that user. Authenticated user making successive requests will send cookie in header from client-side then server validates and updates TTL value for that cookie in DB and on the client-side(Keep-alive session).
JWT-based Authentication: Logged in user send's JWT Token in response. Client stores the token in localStorage and sends the token in header for making requests. JWT stored in DB with TTL value ( 10 Minutes) for that user. Authenticated user making successive requests will send token (taken from localstorage) in header from client-side then server validates and updates TTL value for that token in DB (Keep-alive session).
So, in this approach I don't have to use redis, blacklisting tokens, refresh token etc.
Also, if there is any better solution for this problem-statement kindly, provide your inputs.
Note: The backend is horizontally scaled. The techstack used in backend are Node.js and MongoDB.
Any help, will be appreciated. Thanks in advance.

Using HTTPOnly Cookie in GET request (Retrieve user info from server using user_id cookie)

I'm following a tutorial where, after logging in a user, the backend sends a HTTPOnly cookie to the frontend containing the user id. However, HTTPOnly cookies are not accessible from the frontend (ex. document.cookie will not be able to read the cookie).
My question is, how is this cookie able to be used to retrieve user data? My thought process was that you would do something like GET 'server_address'/user/'id' where 'id' would be the user id stored in the cookie. But this obviously cannot work since the frontend can't access the cookie because it's HTTPOnly. A possible workaround I thought of was for the server to send the user id in the JSON response after logging in, but if this is the solution what is the point of even setting a cookie in the first place? That workaround makes it seem like there's no point in using cookies at all to save user sessions if you can just send the id back in the JSON response.
Please bear with me, this is my first time working with cookies. If it helps at all, I am using an Angular 4 frontend and a Node/Express backend
An httponly cookie is stored in the browser and is automatically resent back to the server with any future requests that match the origin of the cookie. So, the cookie can be used by the server to identify which client is making the request. If, for example, it was an authentication cookie that identifies who an authenticated user was, then the server would know which authenticated user this request is coming from and could use that information to authenticate the request and to know which user it was.
As you seem to already know, the httponly cookie cannot be retrieved by browser Javascript. That is the meaning of httponly.
how is this cookie able to be used to retrieve user data?
The cookie is sent to the server with any request from that client so the server can use the cookie to identify which user is making the request.
A possible workaround I thought of was for the server to send the user id in the JSON response after logging in
If the server wants the client to know the userID, then it should return it in the response. Or, it can stop using an httpOnly cookie so that the client can read the cookie. But, usually cookies that denote any sort of authenticated state are encrypted on the server so they often aren't intelligible to the client, even if they aren't httpOnly.
if this is the solution what is the point of even setting a cookie in the first place
Cookies are used for a variety of reasons. They allow the server to set some state that is associated with that particular client and each future request from that client will send that cookie back to the server so the server can have access to that info. The info could be authentication info, userID info, user preferences, etc...
That workaround makes it seem like there's no point in using cookies at all to save user sessions if you can just send the id back in the JSON response.
You don't really tell us much about your application, but cookies are often involved in implementing login and security and because they are automatically sent along with all future requests, they save the client the both of having to attach credentials to every single future request (because the cookie credential are automatically included). And, for requests such as a user clicking on a link in a page, the cookies are required because those types of links won't have credentials in them (and shouldn't).
My thought process was that you would do something like GET 'server_address'/user/'id'
So you plan to have any security associate with that request? If so, then you need an authentication scheme so that not just anyone can request info for any user. That's often what cookies are used for. You login, the server sets a credential into an encrypted cookie. That credential identifies a particular authenticated user so that for future requests from that same client, the server can use that cookie to see who the user is and whether they are authenticated.
We set cookie as httponly to prevent XSS, imagine if there is a security flaw that allow hacker the inject script <script>sendToHackerServer(document.cookie)...</script>, so user's cookie ( include session) will be sent to hacker server, then hacker can gain access to user data with that session. since these httponly cookie will be readable through http request only, session cookie will not be sent by injected script, and ur express backend can read these cookie with req.cookies.

after successful login the user is redirected to the home page where the SPA loads. Is using session cookie with JWT a bad idea?

I have an express + postgres backend, and I'm using passport-facebook for FB oauth.
If a user hits my app at / without having a valid token in localStorage, they're taken to /login.
My /login page (where you're greeted with the familiar "Continue with Facebook" message) is server rendered (for various reasons). Upon clicking this button, I either verify the user if they exist and send them a session cookie with the initial JWT, or create a new user and send them a session cookie with the initial JWT. In both cases, the success condition is that they are redirected to / and served the SPA assets.
One of the first things the SPA does is take the JWT from the session cookie and put it into localstorage, and then deletes the cookie.
Is this a terrible approach, or is it valid in my use case?
You are using the session cookie as a means to store the JWT on the client. This means that you create a server session that will remain open until it expires, by spending server resources
Session cookies are not readable from javascript, so I guess you make a request to the server to get the JWT, right?
The process does not seem problematic, but I think you could optimize it by sending in your redirection process directly the JWT in the response using a regular cookie with set-cookie header. The cookie will be stored in client and you could access it directly

Node Js refresh auth token

How can you provide example for refresh node js auth token? I mean by what the parameters can I refresh auth token? For example if I can refresh it by login and password then where should I store this params for single-page app? As I understand store it in cookie is not good idea for security, localstorage is not good also because some of browsers not supported it. So maybe someone know another way for refresh token?
Cookies are a very secure storage mechanism, if used correctly. Local storage should never be used for authentication information. OWASP has a great write-up on storage security:
https://www.owasp.org/index.php/HTML5_Security_Cheat_Sheet#Storage_APIs
To quote the important parts:
Do not store session identifiers in local storage as the data is always accessible by JavaScript. Cookies can mitigate this risk using the httpOnly flag.
[With local storage] There is no way to restrict the visibility of an object to a specific path like with the attribute path of HTTP Cookies, every object is shared within an origin and protected with the Same Origin Policy. Avoid host multiple applications on the same origin, all of them would share the same localStorage object, use different subdomains instead.
Back to your original question: where to store the refresh token? Answer: In a HttpOnly cookie. This prevents the cookie from being stolen by XSS attacks, and it makes it very easy for your server to issue new access tokens (using the refresh token) because the server will have access to both at the same time, on the same request.
You can add another layer and encrypt the entire refresh token that is stored in the cookie.
Caution: when using cookies, you also need to protect yourself against CSRF attacks
I’ve written at length about front-end security and JWTs in these two blog posts:
Token Based Authentication for Single Page Apps (SPAs)
https://stormpath.com/blog/build-secure-user-interfaces-using-jwts/
Disclaimer : I work at Stormpath, our service gives you a secure, hosted user database with many features. Our express-stormpath module makes it very easy to get started with login and registration flows for your application. We are in the process of writing a new release, and it will be using access tokens in the way that I describe in this answer.
I created AuthToken model that contain these fields:
user_id, access_token, refresh_token, access_token_expiration
After successful user login, server side will send refresh_token and access_token to client side and store it to localstorage(cookies for old browsers).
And all subsequent requests will be sent with access_token(I use header x-access-token for $httpProvider in angular).
When token expires, client needs to send refresh_token for updating access_token, refresh_token and expiration date. Since I use sockets I can refresh access_token if it is expired in any request(for this I send z-refresh-token header also for each request) so I shouldn't send any extra request and I can keep current user request, just will return tokens via socket event after it was updated.
Hope this helps

Resources