DEV Community

Cover image for Remaining Stateless - JWT + Cookies in Node JS(REST)

Remaining Stateless - JWT + Cookies in Node JS(REST)

Ogbonna Basil on October 22, 2019

JWT is stateless. Using cookies as a container to store JWT is easy and scalable. Why Store in cookies The need to store JWT in cookies...
Collapse
 
belhassen07 profile image
Belhassen Chelbi

The best way to store JWT is the memory, while having an HTTP ONLY cookie containing the refresh token.

Collapse
 
mr_cea profile image
Ogbonna Basil

Thanks Belhassen. I will take a look at this method too.

Collapse
 
reynarow profile image
reza

i heard that many time. but how's the implementation?

Collapse
 
zeeessdoubleu profile image
Zak Williams

Belhassen, when you say store the JWT in memory, are you talking about localstorage, or are you talking about something like Redux or React Context state?

Collapse
 
belhassen07 profile image
Belhassen Chelbi

In the application state (eg: react state).

Thread Thread
 
ghison profile image
Beman Ghison (Behnam Ghiaseddin)

And when user close the browser? Of course, some applications (like banking) prefer to terminate user login, but on most applications, we need to keep user login after closing the browser and open it next time.

Thread Thread
 
belhassen07 profile image
Belhassen Chelbi

the http only cookie for the refresh token stays so you can always get the acces token accessing the refresh endpoint that will give you a new access and a new refresh token so no need to login again.

Collapse
 
mylastore profile image
Oscar Quinteros

Write an example just like Ogbonna Basil ;)

Collapse
 
duacos_89 profile image
Jorge Durango

Great tutorial. Devs always say you should use cookies but never tell you how to do it. By the way, I think I'm doing something wrong because the cookie resets when I reload the page what could be causing this?

Collapse
 
mr_cea profile image
Ogbonna Basil • Edited

The cookie used by the backend is automatically embedded in the header when you make request. Maybe what is happening is that you have authenticated a user in the frontend and then when you reload the page it losses the user information so the user needs to login again. If that is the issue, you need means to identify the authenticated user as the real cookie used in the backend is always embedded in the header and you have no access to it. To solve that problem what i do is to create a fake cookie that identifies the user with non-sensitive information about the user that comes from the response on login or signup and save the fake cookie in the frontend cookie storage. This is because even if an attacker somehow gets the cookie from the cookie storage he cant access information from the backend as that is not the real cookie used by the backend. At the same time the fake cookie helps to keep the user logged in when you reload the page. I hope this is the issue you have. If it is try this approach it worked for me.

Collapse
 
duacos_89 profile image
Jorge Durango

Yes you are right!

it's working now :) thank you

Thread Thread
 
hungrydev39 profile image
Ahmad Reza

Can you provide us with how you implement it. I got kinda confused on how to do this

Collapse
 
vibhprgaalib profile image
Vibhpr-gaalib

always get udefined in req.cookies.toke

require("dotenv").config();
const express = require("express");
const app = express();
const cors = require("cors")
const cookie = require("cookie-parser");
const jwt = require("jsonwebtoken");
app.use(cors());
app.use(cookie());

const createToken = function(res,user){
try{
const token = jwt.sign({user},process.env.ACESS_TOKEN);
console.log(token);
return res.cookie('token', token, {
secure: false, // set to true if your using https
httpOnly: true,
});
}catch(e){
return console
.log(e)
}
}

const verifyToken = async (req, res, next) => {
const token = req.cookies.token || '';
console.log(token);
try {
if (!token) {
return res.status(401).json('You need to Login')
}
const decrypt = await jwt.verify(token, process.env.JWT_SECRET,(err,data)=>{
if(err)res.send("Token is undefined")
});
req.user = {
id: decrypt.id,
firstname: decrypt.firstname,
};
next();
} catch (err) {
return res.status(500).json(err.toString());
}
};

app.get("/",verifyToken,async(req,res)=>{
res.send("Token")
});

app.post("/post",(req,res)=>{
user = {
Name : "vibhor",
Age : "27"
}
createToken(res,user);

});

app.listen(6000,()=>{
console.log("Server has started")
})

Collapse
 
mr_cea profile image
Ogbonna Basil

You are probably getting undefined because you signed the jwt with the secret process.env.Acess_Token but you are trying to verify it with process.env.JWT_Secret. Please correct that and check if it works.

Collapse
 
anassdaoudi profile image
Anass-Daoudi

You really did so great, thanks a lot!!

Collapse
 
bladerunner41 profile image
bladerunner41

gald someone finally put pen to paper show how to use cookies instead of localstorage!

Collapse
 
mr_cea profile image
Ogbonna Basil

Glad you found the article useful

Collapse
 
vibhprgaalib profile image
Vibhpr-gaalib

can't get the cookie when i try to get it req.cookies.token it returns undefined

Collapse
 
sushanth47 profile image
Sushanth

If Your cookies are disappearing and you followed the same code that was given above, i suggest you to change the expiration value to a bigger number as the period of existance of that cookie is only 1 sec. (100ms).

Collapse
 
ortonomy profile image
🅖🅡🅔🅖🅞🅡🅨 🅞🅡🅣🅞🅝

Nice

Collapse
 
lvizcaya profile image
Leonardo Vizcaya Savchenko

This is really how I am working, the JWT with a very short expiration time stored in memory, and the refresh token as you explain only to renew the JWT. Good Post, greetings.

Collapse
 
mr_cea profile image
Ogbonna Basil

Thanks Leonardo. I have looked at storing jwt in memory in the frontend and saving refresh token in http only cookie and i think it is the most optimal approach currently

Collapse
 
donnietd profile image
DonnieTD

Really good post

Deserves more attention.

Collapse
 
mr_cea profile image
Ogbonna Basil

Thanks DonnieTD, glad you found this article helpful

Collapse
 
ramesh123lang profile image
RAMESH MARANDI

thanks for this awesome post.. I really very helpful to you. My code is working Now.