supertokens / supertokens-node

Node SDK for SuperTokens core
https://supertokens.com
Other
278 stars 72 forks source link

Question about cookie expires value #862

Closed ngoquoc closed 2 weeks ago

ngoquoc commented 2 weeks ago

I'm using supertokens-node": "^18.0.0" connecting to a managed instance of SuperTokens from a Hono app (similar to the example app here)

My SuperTokens configuration:

SuperTokens.init({
    framework: "custom",
    supertokens: {
      connectionURI: getEnv("SUPERTOKENS_CONNECTION_URI", c),
      apiKey: getEnv("SUPERTOKENS_API_KEY", c),
    },
    appInfo: {
      apiDomain: getEnv("SUPERTOKENS_API_DOMAIN", c),
      apiBasePath: "/auth",
      websiteDomain: getEnv("WEBSITE_DOMAIN", c),
    },
    recipeList: [EmailPassword.init(), Session.init()],
  });

then the middleware is used as:

const stMiddleware = middleware(() => request);
const { handled, error } = await stMiddleware(request, baseResponse);

for (const cookie of baseResponse.cookies) {
    console.log("🟠 Cookies: ", cookie.key, cookie.expires);
    headers.append(
      "Set-Cookie",
      serialize(cookie.key, cookie.value, {
        domain: cookie.domain,
        expires: new Date(cookie.expires),
        httpOnly: cookie.httpOnly,
        path: cookie.path,
        sameSite: cookie.sameSite,
        secure: cookie.secure,
      })
    );
  }

Everything works just fine except for the strangely large value of cookie.expires in the response of the middleware:

🟠 Cookies:  sAccessToken, expires=4872298825935
  --> POST /auth/signin 500 3s
✘ [ERROR] Error: Cookies Expires SHOULD NOT be greater than 400 days (34560000 seconds) in the future.

What does that number 4872298825935 mean? I tried parsing it as new Date(4872298825935) or new Date(4872298825935/1000) but none of that makes any sense, either too far in the future or in the past.

Also, I tried changing access_token_validity value in the app's setting on this dashboard but it does not seem to take any effect.

How should we interpret that number?

ngoquoc commented 2 weeks ago

Interestingly refresh token expiry date is a proper epoch timestamp:

🟠 Cookies:  sAccessToken 4872301131437
🟠 Cookies:  sRefreshToken 1721293131381
rishabhpoddar commented 2 weeks ago

The access token's cookie lifetime is set to 1 year (which is different from the actual access token jwt lifetime). This is cause the backend needs a way to know if a session exists or not, in case the access token JWT has expired (so that it can distinguish between refresh session vs unauthorised error types).

If we set the access token cookie lifetime to be as much as the JWT itself, then the browser will not send the access token to the backend when it's expired, and it would not cause a refresh, and instead would cause a user logout.

You can set the access token cookie cookie lifetime to a value that is greater that the refresh token's cookie lifetime, but not as much as 1 year (which is what we set). That should work.

ngoquoc commented 2 weeks ago

@rishabhpoddar thanks for the explanation. I think it would be great to have that in the documentations. Also a potential fix might be adjusting sAccessToken cookie's expiry to a valid epoch timestamp that represents 1 year later? Now it seems that it's set to 100 years :)

new Date(4872301131437)
// Thu May 25 2124 15:58:51
rishabhpoddar commented 2 weeks ago

Right, so a correction, we do want to set it to 100 years, which is respected by firefox, but chrome caps it to 1 year anyway. So the code is as expected. Im closing this issue for now since it's not a bug in our SDK.