JWT Refresh Tokens

Thoughts and notes on implementing JWT Auth tokens with refresh tokens

Basic Implementation

Securely Storing Tokens

Seems like there are different opinions on the most secure way to store the tokens in the client. Here are some prevailing thoughts:

Cookies or No?

According to a couple of places, a “secure” way of storing the refresh token is in an HttpOnly cookie. This will work just fine for browser-based applications; however, will it work on native (or React Native) applications?

Given that this is the case, and the security benefits of the HttpOnly cookie (not to mention the ease of not having to manage storing another token), I’m leaning towards implementing the refresh token storage via cookies.

If I’m going to pursue using this, here’s some example code for how to do it using Express:

Setting Cookie in response:

NOTE: This requires the use of cookie-parser, an additional middleware package.

const cookieConfig = {
  httpOnly: true, // to disable accessing cookie via client side js
  //secure: true, // to force https (if you use it)
  maxAge: 1000000000, // ttl in ms (remove this option and cookie will die when browser is closed)
  signed: true, // if you use the secret with cookieParser
};

res.cookie("test", "some value", cookieConfig);
res.send("set cookie");

Retrieving Cookie in Request:

const signedCookies = req.signedCookies; // get signed cookies
console.log("signed-cookies:", signedCookies);
const cookies = req.cookies; // get not signed cookies
console.log("not-signed-cookies:", cookies);
// or access directly to one cookie by its name :
const myTestCookie = req.signedCookies.test;
console.log("our test signed cookie:", myTestCookie);

Setting Expiration Dates on JWT

JWTs have their expiration by setting the exp claim on the payload. This claim specifically is set as the seconds since the Unix epoch of the date in which the token expires. E.g.:

// Sets the token to expire in 1hr
jwt.sign(
  {
    exp: Math.floor(Date.now() / 1000) + 60 * 60,
    data: "foobar",
  },
  "secret",
);

However, using the Node package node-jsonwebtoken, you can set it even easier with their options argument in the sign() function:

jwt.sign(
  {
    data: "foobar",
  },
  "secret",
  { expiresIn: 60 * 60 },
);

//or even better:

jwt.sign(
  {
    data: "foobar",
  },
  "secret",
  { expiresIn: "1h" },
);

Managing “Remember Me” Sessions

TODO: Add more here.

Further Reading

Tags