next.jsjwtvercelhttp-status-code-304

Next-App deployed on Vercel: Request for new refresh-token leads to unwanted 304 Not Modified-response


I built a Next-app on the frontend and deployed it on Vercel (and a Django-app on the backend deployed on Heroku). Authentication is implemented with JWTs and and a Next-API route connecting the Next-Frontend with the Django-Backend.

The authentication workflow relevant for my problem is the following:

Whenever an authenticated user visits a protected page, a request (with the current refresh-token) is sent to the backend, asking for a fresh pair of access & refresh tokens. This works perfectly fine when testing locally the production-optimized version of the Nextjs-app (via next build & next start): I receive a 200 OK response with the new refresh- and access-tokens.

However - when I do the same thing in my Vercel-deployed app, after the first request/response-cycle for new tokens (which works as expected), I always get back a 304 Not Modified-response, which does not have any cookies in its Headers. I can see that my Django-server sends off the new tokens but somehow they get lost on the Next-server.

I did some research and if I understand correctly, Vercel has some caching rules, that lead to this behavior. However, I could not find any solution on how to avoid this from happening.

Does anyone know, what to do in this case?


Solution

  • I figured it out by myself, sharing the solution for anyone who might run into this problem in the future. When it comes to caching - Vercel's production servers behave differently than the test server you can run with npm run start. While the former caches certain responses by default for performance reasons, the latter does not do that.

    To deactivate the caching for the response giving me the unwanted 304 Not Modified status, i simply added a Cache-Control-header with no-cache, no-store, max-age=0 and must-revalidate directives to it:

    export default async function refresh(req, res) {
      ...
      if (apiRes.status === 200) {    
        // "Cache-Control"-header needed for production to avoid Vercel's default 
        // response caching mechanism        
        res.setHeader(
          "Cache-Control",
          "no-cache, no-store, max-age=0, must-revalidate"
        );
        ...