JWT - Refreshing tokens, and security improvments - security

I'm developing a new web app with NodeJS and ReactJS and I'm using JWT for authentication. The client side sends a request to /login using axios.post(), the server checks the data entered by the user and returns an access token with an expiration time of 5 minutes and a refresh token. I use Redux to save tokens at the app level state. On next requests, the client side sends back the token to the server.
My questions are:
1) Is there a way to open multiple tabs and recover the state of the first tab opened and when the user logs out of a tab, he is logged out of all tabs? (Facebook uses this method)
2) Imagine I connect to the website at a friend's place and when I leave I forget to disconnect, is there a way to disconnect from all the devices when I get home? (Facebook uses that too)
3) Is it possible to automatically delete the tokens in the app level state after X seconds / minutes only when tabs are closed and continuously refresh the access token otherwise?
Thank you in advance

No answer to your post after 9 days. Too bad, let me help you out.
To get the closest representation of what you want i would use a SameSite Cookie.
They're always on all Tabs and you can also expire them after a period of time.
Cookie will get deleted and you'll be logged out.
In order to work with devices you can use a blacklist on your refresh tokens, although this is against the principles of JWT it is still a possibility.
SameSite Cookies spread over all tabs
The Cookie can be send with all requests in the header (use strict mode)
Deleting the Cookie results in a logout
Blacklisting the Refreshtoken JWT will result in a logout of the user aswell.
Would recommend you to read about the SameSite cookie (strict). You'll be surprised because there's not alot of people who know about it.
If i can be of any help feel free to contact me through DM.

Related

httpOnly cookies with React and Node

I'm trying to figure out how to implement authentication/authorization with React and Node, using httpOnly cookies, with scalability optionality. I've read JWT can solve this by using refresh tokens and httpOnly cookies.
The number one problem for me is how to make it work the right way with react, because the httOnly cookie isn't accessible via JS.
The second thing is, I want my frontend and backend to live in separated, dockerized containers, but as far as I got it, the httpOnly cookies are added to the headers only for the same domain(and same port).*Update Actually, I've just read this is not true and I can use httpOnly cookie on same host, but different ports.*Update2, I've remembered what it was about: the "SameSite" property on the cookie. This will bind the cookie to the same origin, meaning port difference will consider as different origin and the cookie will not be transferred.
Can you please clarify this and maybe explain, does it really so important, I mean am I really will be in danger if I want to use some super-ultra-highly-secure website and yet, will use JWT with local storage(but with refresh tokens)? Does the httpOnly(and sameSite: true) cookies really will make a difference here?
Thanks
In my project (which is also Node + React) I did the following:
For each authenticated user (username + password) I signed two tokens, an access token and a refresh token.
I set the refresh token in the response header using httpOnly attribute. beware that latest versions of browsers won't allow third party cookies (from different domains) unless you set the attributes Secure and SameSite.
I return the access token as my response's body
Now in the client side (your React app):
You will get the access token in the response body, and here you have two options. To store it in local storage, or in memory. I chose to keep the token in memory instead because of a XSS vulnerability. (This obviously requires you to get another access token on each page refresh since the memory is cleared)
The refresh token is not accessible through JS you are right, but you don't need it. This token will be sent on each request, and usually it's expiration date should be a long one (I set it to 6-12 months)
Every time you want to gain a new access token (because it's expiration time should be
a small one, about 15-20 minutes), you will send a request to the server to "refresh" your access token, and the server will just check if the refresh token exists in the request headers, if not return a status of Unauthorized
EDIT: jwt tokens are not "secure" or "not secure", they are just tokens containing some data, and they allow you to make your authentication processs stateless (instead of managing sessions in your server). As long as you don't store any sensitive data in them, and sign them with a secret key that only you possess, you should be fine
EDIT 2: Since you are using react which "sanitizes" the DOM, a possibility of XSS is a minor one, so using local storage is ok and lots of websites do it. But because there is still a possibility (of you or a client injecting a script to some input element), I decided to store the access token in memory, which is a bit of a overhead but I prefer that.

Where jsonwebtoken stored in server nodejs . How to expire JWT once user gets logout

I am storing Tokens on Session/Local storage on the client side.The problem I am facing is once a user copies that token and uses it for other logged-in session services it works but it should return invalid token on JWT.varify.
Is there any way to Blacklist/Delete/Expire currently used token once a user has logged out?
There a a few ways to set up a blacklist for that purpose:
1) (Blacklist users in the database) Add a database column isTokenExpired for users and set it to false on a successful login, and true when you want to expire the token (for example when the user changes their password, logs out, or enough time has expired).
The above method will achieve your purpose, but I feel it is an insult to programming. I assume you are using JWT so that the user doesn't have to log in every time, and that you have only 1 server which is doing the authentication and all other server functions. Although JWT was not designed for "sessions", using JWT for this purpose can take load off the database. But if you are then setting and checking another database flag on every user action, you are adding that load again, and you still have all the load associated with the JWT etc, so you might as well just re-auth on every user action.
2) (Blacklist a user/the token in server RAM) When I researched this problem for myself (how to invalidate individual tokens), I found some solutions where the server maintains either a whitelist or blacklist in RAM, so without adding database or file load. This may be a somewhat better solution, but I can't remember the names of any of the libraries that facilitate this. Maybe someone else can mention some of them.
3) Set token to a very short expiry time (For example 60 seconds or 5 minutes) and set up the client to automatically request a new token every (~55 seconds or ~4 minutes 50 seconds). The server would then check and validate the token in the same way I assume you are doing it now, without accessing the database, and would then generate a new token with the same values for all the other fields, but with a new "expiry time" value, and send that token back to the client where it would replace its JWT with this new JWT, and re-start its 5-minute timer. This is a good balance between the other choices, and maintains some of the benefits of using the JWT, but does add some small cost. I think this is a pretty good solution for many applications, but it definitely depends on the specific application, but it is somewhat hacky and definitely not "the right way" to do it.
4) Use JWT + Sessions This is "the right way" to do it. After all my research a long time ago, I realized that JWT's are not designed to be used for maintaining sessions: JWT is only a secure way of representing a claim. Imagine having a large system with tens of millions of users, and you require many servers around the world. You may have 3 authentication servers (in USA, Australia, UK). The user will then send its username and password to an authentication server, where the details will be checked in the database, and if valid it will be sent a JWT. You may then also have 10+ regular servers which handle your API. The client will then make each request to an API server with its JWT. The API server will have a copy of the secret key that was used by the authentication server to generate the JWT, and will validate your claim. Your claim is "I am authenticated". This API server will then generate a session and the client will be "logged in". The JWT may be set to expire after 5 minutes. If the user does not log in within this 5 minutes, they will not be able to log in. If they do, they will be logged in until the API server kicks them out. Whenever something happens that would cause you to want to kick the user, the API server can close the session. Even for a single-server application this is still the right way to do it. JWT are not for sessions, and you (exactly as I did) are starting to notice these seemingly unsolvable problems because you are using JWT for sessions.
Anyway, I recommend 3 or 4, both of these options have a net-positive value for many applications.
1 and 2 seem to make more problems than the benefits they provide.
But of course, it always depends on the application. If you're just making some website on fiverr for $5 then just do whatever, you know what I mean?
If there's a better solution I'd be interested to know too! Just remember that JWT represents a claim, and consider exactly what claim your client is representing.
Answering your first question (where is JWT stored in server Node.js)
JWT tokens are not stored on server side. It is a signature(by a secret key, RFC 7519 ) based authentication system.
So server just verifies the token and if it's verified then it gives access to the user and hence any user having your token can act as you.
For example - you can copy cookies/storage of a logged in facebook user and then go to another browser and set those cookies/storage. You will be logged in as that user for a few.
FYI #safebookverified 3rd way is mostly used. thanks.

How should I store a token generated by a RESTful API?

I have built an API that generates an authentication token for the users that log in. At this time I also have a client application written in Node.JS.
When I make the request with the user credentials from the client application to the API I get the authentication token: how should I store it in the client application? I'm not supposed to request a token every time I want to make a request for the API, correct?
I thought about putting the token in a Cookie, but I don't think that's the best solution.
What would you recommend?
Upon successful login, a unique, one-use token should be created server side and stored in the database against a user id and timestamp. You store the token in a cookie client-side. You then pass the token up to every subsequent API call. The server should then check the token is valid (ie not expired, say issued or update less then say 30 minutes ago). If it is valid, you can retrieve the user details stored against that token and perform whatever backend functionality you need (as the user is authenticated). You then update the timestamp for that token (refresh the session as you want the login to time out after say 30 minutes of no user interaction). If a token is expired or non-existent when you get the API call, redirect to the login page.
Also, you probably know this already, but make sure the token is unique and non-guessable, I tend to generate new random GUIDs and encrypt them, do not use sequentail ids or anything like that.
I think that this link could help you:
Implementing authentication with tokens for restful applications - https://templth.wordpress.com/2015/01/05/implementing-authentication-with-tokens-for-restful-applications/
In fact, you should have a token with an expiration date, so you don't have to get a new token each time before sending a request. When the token expires, you simply need to get a new one from a service "refresh token".
Regarding the question about how to store the token in the client application, I think that you could keep it in memory (map or embedded database).
Otherwise to finish, I don't think that it's a good idea to use cookies in such use case.
Hope it will help you.
Thierry
We're working on an application that uses a very similar approach. The client application is a static HTML5/JS single-page application (with no server-side generation whatsoever) and communicates with an API server.
The best approach is to store the session token in memory: that is, inside a variable in the JS code. If your client application is a single page, it shouldn't be a problem.
In addition to that, we also keep the session token in sessionStorage to preserve it in case the user refreshes the page. To preserve the token when new tabs are created (sessionStorage is specific to a browser window), we also store it in localStorage when the page is being closed, together with a counter for open tabs (when all tabs of the application are closed, we remove the token.
// Handle page reloads using sessionStorage
var sess = sessionStorage.getItem('session-token')
if(sess && sess !== 'null') { // Sometimes empty values are a string "null"
localStorage.setItem('session-token', sess)
}
// Set a counter to check when all pages/tabs of the application are closed
var counter = parseInt(localStorage.getItem('session-counter') || 0, 10)
counter++
localStorage.setItem('session-counter', counter)
// Event fired when the page/tab is closing
window.onbeforeunload = function() {
var counter = parseInt(localStorage.getItem('session-counter') || 0, 10)
counter--
localStorage.setItem('session-counter', counter)
// All pages are closed: remove the session token
if(counter <= 0) {
// Handle page reloads using sessionStorage
sessionStorage.setItem('session-token', localStorage.getItem('session-token'))
localStorage.removeItem('session-token')
}
}
For more information about localStorage and sessionStorage: https://developer.mozilla.org/en-US/docs/Web/API/Web_Storage_API
Why not cookies? Cookies are bad for two reasons:
1. They are generally more persistent, being shared across browser windows and tabs, and they can persist even after the browser is closed.
2. Most importantly, however, by the HTTP specifications they must be sent to the web server every time a request is made. If you're designing an application where the client is completely separated from the API server, you don't want the client's server to see (or log!) the session token in any case.
Some extra advices:
Session tokens must expire. You can achieve that by storing session tokens in the database on the server and verifying them on every request and/or "signing" them (adding a timestamp to the token in plain text, then adding a signed part, for example a HMAC hash, with the timestamp encoded with a secret key you only know).
Tokens can be reused as many times during their life. However, after a certain number of seconds you may want your server to refresh the tokens, invalidating the old one and sending a new token to the client.

How exactly does Auhtorization in web applications work?

First, i know that there are to components of handling user access to restricted pages in web appliations.
Authentification is about identifying a user.
Authorization: is about determining what parts of the application an authenticated user has access to
I belive this is made with session id.
But does the client have to send the session id with every request he makes? If not how can he be authentified? Or is a cookie used for this?
Sessions exist on the server. They are sometimes (usually) identified by a cookie.
The session can contain a multitude of information that is relevant to the session. E.g. shopping basket.
Server gets the cookie. Looks up the session. Has it timed out? Is it from the same IP address? From the same browser perhaps? Then use the stored information for the generation of the web page
Session still among pages, but it would be destroyed when you close your browser
Cookies still sometime when the time expires

Can I disable a cookie from being sent automatically with server requests?

I'm fairly new to website development. I'm working on a site where the user logs in with username/password, and gets a sessionID from the server in response. This sessionID is sent back to the server (and a new one returned) with each request.
I'd like the site to work properly if the user opens it in multiple tabs or windows. i.e. once logged in at one tab, opening a members-only URL in another tab works without loggin in. (And, logging out in one tab logs out from all.) I see no way of doing this without storing the latest sessionID in a cookie. That way the latest sessionID can be "shared" among all tabs.
However I am starting to read up on cookies, and some of the security threats. I was unaware that cookies were sent with every request. I don't need to send my cookie to the server, ever. The sessionID is added to the xhr request's headers -- not read as a cookie. So I'm wondering if there is a way to disable sending of this cookie. My only purpose for it is to allow multiple tabs/windows in the same browser to share the same session.
I was reading up on the path parameter for cookies. Apparently this can be used to restrict when the cookie is sent to a server? What if I set the path to something that would never be used? Would this prevent the cookie from ever being sent out automatically? I only want to access it from JavaScript.
A coworker has put a lot of safeguards into the server-side of this application, which I won't go into here. So this question is just about what client-side precautions I can and should take, particularly with cookies, for optimal security. If there is a better way to allow a members-only site to work properly with multiple tabs open at once, I'm all ears.
I discovered just now that in HTML 5 there is local storage, which stores key/value pairs much like a cookie, but is not sent with every server request. Since it's supported in every browser except IE 7 and earlier, I'll be switching to this to enable sharing data between tabs when available, and use cookies instead on IE 7 and earlier.
The sessionID is stored in a cookie already there's no need to manage it. Because the HTTP protocol is stateless the only way to maintain state is through a cookie. What happens when you set a session value the server will look up the dictionary of items associated with that cookie id (session Id).
What is meant by stateless is that between requests HTTP does not know if your still alive or have closed your browser. Therefore with each request the browser will attach all cookie values to the request on the domain. SessionId is stored in the cookie automatically when they go to your site. The Server then uses that value to look up anything you've set in the users session.
Depending on which programming language and/or server you're using the session could be handled differently but that's usually abstracted away from the programmer.
Now with respect to sessions, there are a number of different things that make them insecure. For example if an attacker were able to get their hands on your session cookie value they could replay that cookie and take over your session. So sessions aren't a terribly secure way of storing user information. Instead what most people do is create an encrypted cookie value with the users details, the cookie could be a "session cookie" meaning as soon as the user closes their browser window the cookie is thrown away from the browser. The encrypted cookie contains user information and role information as well as some identifier (usually the clients ip address) to verify that the user who is submitting the request is the same user the cookie was issued to. In most programming languages there are tools that help in abstracting that away as well (such as the ASP.NET membership provider model).
Check out some details on the HTTP protocol and HTTP cookies on Wikipedia first
http://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol
http://en.wikipedia.org/wiki/HTTP_cookie
and check out the membership provider model on ASP.NET, it's a really good tool for helping to secure your site.
http://msdn.microsoft.com/en-us/library/sx3h274z(v=vs.100).aspx
Preventing the browser sending cookies seems to defeat the object of using cookies in the first place.
If you don't want the sessionID to be sent with each request, why set the cookie? A better solution would be to use a custom response header that you send from the server to the browser - this will then be under your control and will not be sent automatically with all browser requests. You are using request headers to send your sessionID anyway so you could receive them from the server using a custom header and read this into your JavaScript from each XHR.

Resources