Search code examples
javascriptexpresssessioncookiesremix.run

Session Coookie keeps getting reset in Remix/Express


I am using Remix, using the indie-stack template, which i modified to use Express.

I am currently trying to get the authentication to work. I am using the same flow that is used by the default, the createCookieSessionStorage flow, which as the name suggests uses cookies to store the session.

When i log in, the session gets properly created and i can see it in the cookie. It looks something like this:

enter image description here

This is all well and fine, and i can extract the logged in user from this.

However, whenever this cookie exists, whenever i enter any of my routes a redirect happens that passes a set-cookie header that nullfies this cookie. See below:

Fist, after i log in, the set-cookie gets set correctly: enter image description here

Then, when i visit ANY page, this gets fired off: enter image description here

This happens if i have the __session cookie with the value that was set there after the log in. I don't even have to log in, as this happens even if i manually set this cookie in there with that value. If i change the value, no redirect and no set-cookie: path=/ gets fired off.

Any idea why this is happening? Its as if the server reads the value of the cookie and decides it needs to remove it. I am using the exact same authentication code as the remix indie stack starts with, see below:

export const sessionStorage = createCookieSessionStorage({
  cookie: {
    name: "__session",
    httpOnly: true,
    path: "/",
    sameSite: "lax",
    secrets: ["super-duper-s3cret"],
    secure: process.env.NODE_ENV === "production",
  },
});


export async function createUserSession({
  request,
  userId,
  remember,
  redirectTo,
}: {
  request: Request;
  userId: string;
  remember: boolean;
  redirectTo: string;
}) {
  const session = await getSession(request);
  session.set(USER_SESSION_KEY, userId);
  return redirect(redirectTo, {
    headers: {
      "Set-Cookie": await sessionStorage.commitSession(session, {
        maxAge: remember
          ? 60 * 60 * 24 * 7 // 7 days
          : undefined,
      }),
    },
  });
}

To note again, i am not sure if this is a remix issue or an express issue. I am using Remix with Express.

Please let me know if more details are needed!

Thank you in advance!


Solution

  • I discovered the reason behind my session getting destroyed.

    In the app, in order to get the logged in user, i use the getUser function that is also provided by the indie-stack template. It looks like this:

    export async function getUser(request: Request) {
      const userId = await getUserId(request);
      if (userId === undefined) return null;
    
      const user = await getUserById(userId);
      if (user) return user;
    
      throw await logout(request);
    }
    

    And that logout method at the end looks like this:

    export async function logout(request: Request) {
      const session = await getSession(request);
      return redirect("/", {
        headers: {
          "Set-Cookie": await sessionStorage.destroySession(session),
        },
      });
    }
    

    This method was the reason i was losing my session. I guess on some initial render the user is not found and the session killed. I will look into why my app is behaving that way, but this is confirmed the reason why I am losing the session.