How should I store a token generated by a RESTful API? - node.js

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.

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.

JWT - Refreshing tokens, and security improvments

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.

Session vs Cookie, what's the difference?

I have a question about Sessions and Cookies on Node regarding where they are stored and how they work.
To begin with, I understand the following to be true:
With a cookie, it is possible to specify how long it will store your data;
A session saves data while the browser is open;
Cookies are on the client side;
Session is on server side;
Then the following questions arise:
How does the browser and/or the server know that the user has already
logged in and does not need to log in again?
If the Session stays inside a cookie what's the difference?
Where are cookies stored? In the web browser?
I use the (Blackberry?) passport (browser?) but it does everything by itself. I want to better understand how it works behind the scenes.
My affirmations can be wrong. You can correct me, but please explain to me.
Regarding what you understand to be true:
Yes, when setting a cookie, you can specify how long it will persist. In the article HTTP Cookies in Node.js, see the section entitled
"Adding Cookie with expiration Time".
Yes, data can be stored in a
session if it is explicitly placed there by application code. Your server software may also use it to store other information. Here
is a nice short YouTube video on node.js sessions.
Cookies are stored in a file on your computer which is managed by your web
browser, so again, correct. Here's a nice article that explains in more detail: Cookies - Information that websites store on your computer.
As to your other questions:
How does the browser and/or the server know that the user has already
logged in and does not need to log in again?
It generally knows this by storing a cookie in your browser whose value is some sort of session ID that acts as an authentication token. When you are successfully authenticated, it will store a cookie and send this cookie's value as an HTTP header or as part of the URL string, etc. each time you make a request to the server. This token is stored on the server with some sort of expiration time, usually something like 15-60 minutes. The expiration timer is reset to zero with each successful request. If session timeout is 30 minutes for example, the token will be invalid after no request is made within 30 minutes. Therefore, if you walk away from your computer for an hour and try to access another page, you will likely be told you need to log in again.
If the Session stays inside a cookie what's the difference?
As I stated in the answer to the previous question, an authentication token is generally stored as a cookie and sent with each request. It's good to use over and over until the session times out.
So, the difference is: A session is stored on the server. A cookie is stored as a file on your computer by your browser. A session cookie is stored on your computer which is used by the server to track individual user sessions.
Where are cookies stored? In the web browser?
Yes, as stated above, cookies are stored in a file on your computer which is managed by your web browser. See the article I linked to above for more detail.
First off, some general facts.
A cookie is stored in the browser and then sent back to the target server with every request to that server.
A cookie can either contain actual state data (such as backgroundColor=blue) or it can just contain a token that only means something to the server.
Whoever sets a cookie decides how long they want it to last before it "expires". If the server sets the cookie (as cookies can also be set from within Javascript in the web page), then the server decides how long they want the cookie to last.
A server session consists of the server creating a unique token and putting that in a cookie that it sets for that browser. In parallel, it also creates a session object that is stored on the server and it creates a means of associating the token with a particular session object such that when a request comes in and it has a particular token in it, the server can find the corresponding session object.
Note, sessions don't have to use cookies. They can also put a session id in the URL itself and that is occasionally used, but isn't very popular for a variety of reasons.
How does browse and / or server know that the user has already logged in and does not need to log in again?
A server can consider a browser to be already logged in if it finds an appropriate cookie in the incoming request and if it finds an associated session object in the server-side session store and if that session object is both logged in and not expired.
If the Session stays inside the cookie why is this difference?
Usually, when using server-side sessions, all that's in the cookie is a unique token - not any of the actual session data.
Where is the cookie stored? In our browser?
Yes, it's stored on your hard drive by the browser and then sent as an http header along with every request to the server that the cookie is associated with.

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.

CSRF in Go Web Applications

I want to implement CSRF prevention in my Go web application. Users don't log in, but they do fill out forms and pay (via Stripe Checkout).
Posting something sets a key in a session variable (cookie) so they can later edit what they've posted, and a URL in an email allows them to come back when the cookie has expired and edit it again if need be.
From what I can see, I can use https://code.google.com/p/xsrftoken/ with the "double submitted cookie" method to implement CSRF prevention by:
Generate a CSRF token against an arbitrary user ID (uuid.V4() via go-uuid), like so:
if session.Values["id"] == "" {
session.Values["id"] = uuid.NewV4()
}
csrfToken := xsrftoken.Generate(csrfKey, session.Values["id"], "/listing/new/post")
... and store that in the session and render it in a hidden field in the template:
session.Values["csrfToken"] = csrfToken
...
<input type="hidden" id="_csrf" value={{ .csrfToken }}>
When the user submits the form, I need to get the ID I generated, confirm that the submitted csrfToken from the form matches the one in the session, and if so, validate it with the xsrf package to confirm it hasn't expired:
userID := session.Values["id"]
if session.Values["csrfToken"] != r.PostFormValue("csrfToken") {
http.Redirect(w, r, "/listing/new", 400)
}
if !xsrftoken.Valid(session.Values["csrfToken"], csrfKey, userID, "/listing/new/post") {
http.Redirect(w, r, "/listing/new", 400)
}
My pertinent questions are:
Should I generate a new token every time the form is rendered? Or is it acceptable to re-use a non-expired token for a single user session? Update: According to this answer I should only generate a new token per session (i.e. so the same user gets the same token on the same form, until the token expires)
Given the updated question, how do I handle the situation where a created token expires between the time the user requests the form and then submits the form? (perhaps it had 10 minutes left, and they alt+tabbed out for a while) Re-direct them back to the form (re-populated, of course!) and generate a new session id + csrf token?
Is there a different way to do this? Coding Horror indicates that SO generates a unique key for every HTML form sent to the client? How would I go about going down this route with the xsrf package, given that it wants a userID when generating a new key?
What else have I overlooked?
Should I generate a new token every time the form is rendered? Or is
it acceptable to re-use a non-expired token for a single user session?
Update: According to this answer I should only generate a new token
per session (i.e. so the same user gets the same token on the same
form, until the token expires)
It is a good idea to regenerate both the token and session ID often. Given a persistent attacker and a viable entry vector, it's just a matter of time until the attacker obtains both. If, however, at least one of both identifiers regenerates before the attacker is able to crack the current one, then no problem.
Given the updated question, how do I handle the situation where a
created token expires between the time the user requests the form and
then submits the form? (perhaps it had 10 minutes left, and they
alt+tabbed out for a while) Re-direct them back to the form
(re-populated, of course!) and generate a new session id + csrf token?
You can update cookies and CSRF tokens through AJAX if you want to give your client vast time to fill out a form.
Is there a different way to do this? Coding Horror indicates that SO
generates a unique key for every HTML form sent to the client? How
would I go about going down this route with the xsrf package, given
that it wants a userID when generating a new key?
The more tightly bound a token is to a certain action that requires authentication, the more fine-grained control you have. If you can uniquely identify each form in your application then I'd say do it.
I've created a CSRF protection package for Go called nosurf. Here's how it handles the areas you mentioned:
Token is created by taking bytes from CS PRNG and encoding them using base64. It is not regenerated for every page load or every form, though there is a user-callable function for regenerating the token.
It is then stored in a cookie (not a session, as it's a generic middleware not intended for any specific framework only). The cookie lasts one year, but you can easily modify this duration.
nosurf takes care of cancelling the request and either returning 403 or calling your custom failure handler (if set). You don't have to have if CsrfCheckOk(r) { ... } or anything like that in your code.
Sadly, it doesn't address token expiring inbetween the page load and the form submission.
So that's it, even though I'm not sure it is the best way to handle CSRF all-around. A package for a specific framework might handle it better in some ways due to tight integration.

Resources