'SvelteKit not setting cookie on page refresh

Every request to my API has a retry in case it fails with 401. In that case, it generates a new JWT and returns it from the endpoint.json to the handle function by setting the "event.locals.user" with the new JWT.

This is my hooks file:

import { parse, serialize } from "cookie";

/** @type {import('@sveltejs/kit').Handle} */
export async function handle({ event, resolve }) {
  event.locals.user = getUserInformation(event.request.headers.get("cookie"));
  const response = await resolve(event);

  if (isRequestFromEndpoint(event.request)) {
    if (shouldDeleteJwtCookie(event, response)) {
      response.headers.set(
        "set-cookie",
        "jwt=deleted; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT"
      );
      return response;
    }

    if (shouldUpdateJwtCookie(event)) {
      const jwt = serializeNewJwtCookie(event.locals.user);
      response.headers.set("set-cookie", jwt);
    }
  }

  console.log(response);

  return response;
}

function shouldDeleteJwtCookie(event, response) {
  return (
    isUnauthorizedResponse(response) && isRequestFromEndpoint(event.request)
  );
}

function isUnauthorizedResponse(response) {
  return response.status === 401;
}

function isRequestFromEndpoint(request) {
  return request.url.endsWith(".json");
}

function shouldUpdateJwtCookie(event) {
  return hasUserInfo(event) && isRequestFromEndpoint(event.request);
}

function hasUserInfo(event) {
  return !!event.locals.user;
}

/** @type {import('@sveltejs/kit').GetSession} */
export function getSession(event) {
  return hasUserInfo(event)
    ? {
        user: {
          name: event.locals.user.name,
          email: event.locals.user.email,
          subscription: event.locals.user.subscription,
        },
      }
    : {};
}

function getUserInformation(requestCookie) {
  const cookies = parse(requestCookie || "");
  const jwt =
    cookies.jwt && Buffer.from(cookies.jwt, "base64").toString("utf-8");
  return jwt ? JSON.parse(jwt) : null;
}

function serializeNewJwtCookie(user) {
  const json = JSON.stringify(user);
  const jwt = Buffer.from(json).toString("base64");
  return serialize("jwt", jwt, {
    httpOnly: true,
    path: "/",
  });
}

Navigation between routes through the entire site works perfectly, cookies are set correctly when needed. The problem only occurs when hitting refresh, the new JWT cookie is not set, it remains with the previous one.

Log:

Blue: Normal route navigation Green: Page refresh

So the problem is that the svelte handle hook is called two times. One for the "carteiras.json" endpoint, which has the correct event.locals.user jwt. And one for the "carteiras", which has the old event.locals.user jwt.

Browser network requests when refreshing page

It seems that when refreshing the page, the "carteiras.json" endpoint is called from the svelte server only, so it doesn't sets the cookie in the browser.

When doing normal route navigation the "carteiras.json" endpoint is called from the browser and then updates the cookie correctly.

Browser network request - normal route navigation



Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source