5

I'm having an authorization (JWT) related caching issue when using Nuxt.

This is the nuxtServerInit action, where I set the access token:

// store/index.js

import cookie from 'cookie';

export const state = () => ({
  authCookie: 'MyAuthCookie',
});

export const actions = {
  async nuxtServerInit({ dispatch, commit, state }, { req }) {
    // Check for access token
    const accessToken = req.headers.cookie &&
      cookie.parse(req.headers.cookie)[state.authCookie];

    // Set the access token, if there is one
    if (accessToken) {
      commit('auth/setAccessToken', accessToken);
    }
  },
};

The accessToken state is later used to set the Authorization header for all future requests in this plugin:

// plugins/axios.js

export default function ({ app, store }) {
  app.$axios.onRequest((config) => {
    // Set the `Authorization` header for future requests if we're logged in
    if (store.getters['auth/isLoggedIn']) {
      config.headers.common.Authorization = `Bearer ${store.state.auth.accessToken}`;
    }
  });
};

Nuxt stores data shared between client and server in a global window.__NUXT__ variable in an inlined <script> tag, and because I am aggressively caching the page in question (using Akamai), the access token will never be updated.

Is there a better way of handling this, and to prevent the access token from being cached? Or in other words how do I prevent the accessToken state to be written to the global __NUXT__ variable?

jdlm
  • 6,327
  • 5
  • 29
  • 49
  • Could you use asyncData per page to set the AccessToken on each pageload client side? – reddiky Jan 17 '20 at 18:51
  • Same issue here- did you ever find a resolution? This is a big security issue as it can cause people's credentials to be cached server side :( – Nick Barrett Jan 22 '21 at 02:35
  • @NickBarrett No, unfortunately. Yes, that was/is our exact issue. We ended up caching everything except the page itself. – jdlm Jan 22 '21 at 13:38
  • @jdlm Yeah fair enough- we have opted to include the headers on non-authenticated requests but leave them off for authenticated ones. – Nick Barrett Jan 24 '21 at 00:31

3 Answers3

2

Try adding below the header on each request so it will not cache headers

config.headers['Cache-Control'] = 'private, no-cache, no-store, must-revalidate';
Hardik Shah
  • 1,366
  • 2
  • 15
  • 35
0

The only thing I can think of is filling the store on both, server and client side.

Server side is already covered with nuxtServerInit.

Client side could be done with a client side plugin, like described here: https://github.com/nuxt/nuxt.js/pull/4573#issuecomment-557857101

jumper85
  • 472
  • 3
  • 9
0

I come up with the similar problem. in my case, I login, then route byside, when I route back with the browser's go back button, the question appears, i.e. within nuxtServerInit, req.headers.cookie can't be read correctly. I find out it's because the document is read from browser's disk cache. so , updated cookies can't be read out. so, I forbiden document cache within nuxtServerInit, and it worked out

async nuxtServerInit({ dispatch, commit, state }, { req, res }) {
    // forbid browser cache html document
    res.setHeader("Cache-Control", "no-cache, no-store, max-age=0, must-revalidate");
    res.setHeader("Expires", "0");
    res.setHeader("Pragma", "no-cache");
    
    
    // Check for access token
    const accessToken = req.headers.cookie &&
      cookie.parse(req.headers.cookie)[state.authCookie];

    // Set the access token, if there is one
    if (accessToken) {
      commit('auth/setAccessToken', accessToken);
    }
  }