vvo / iron-session

🛠 Secure, stateless, and cookie-based session library for JavaScript

Home Page:https://get-iron-session.vercel.app

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

v6 and Next 13 pages middleware

viachaslau-latushkin opened this issue · comments

Hi!
Thank you for your work!

I faced with problem in v6: save() and destroy() not working before return in nextjs middleware.
And changes applying only on next tick or after reloading page or on new request to pages/api folder.

"iron-session": "^6.3.1",
"next": "13.2.4"

@viachaslau-latushkin ➡️ vercel/next.js#49442 (comment)

Thank you!
But in this case cookie from middleware is not encrypted.

Hello @viachaslau-latushkin ,
iron-session adds the encrypted cookie via the "set-cookie" header, so the applySetCookie method applies the correctly encrypted cookie!

What makes you think otherwise?

@Thanaen in middleware I am trying to apply refresh token logic.
I get a new token and try to rewrite cookie with new encrypted (encrypted token) value.
Yes, applySetCookie really add new cookie from middleware and it exists in next steps.
But how get new encrypted value with help of iron-session which will be encrypted in middleware with help of sessionOptions.password and after successfully decrypt this value (again with help of sessionOptions.password) in time of SSR or in Api Router handler?

You can use sealData() and unsealData() to encrypt/decrypt the cookie values.

Assuming you're doing an oauth/refresh token kind of thing, here's something I used recently:

import {
  IRON_COOKIE_NAME,
  SessionData,
  ironOptions,
} from './auth';

export async function middleware() {
  const session = await getIronSession<SessionData>(cookies(), ironOptions);
  const next = NextResponse.next();

  if (!session.token?.expires_at) {
    // no/invalid token, send user to auth
    return NextResponse.redirect(getGoogleAuthURL());
  }
  if (session.token.expires_at < Date.now()) {
    // refresh token
    try {
      const token = await refreshToken(session.token);

      const sealed = await sealData(
        {
          ...session,
          token: { ...token, expires_at: Date.now() + token.expires_in * 1000 },
        },
        ironOptions,
      );
      next.cookies.set(IRON_COOKIE_NAME, sealed);
      // await session.save(); // won't work
    } catch (e) {
      // some error while refreshing token, send user to auth
      console.error(e);
      return NextResponse.redirect(getGoogleAuthURL());
    }
  }

  return next;
}

@arthurjdam
Thank you.
Nice solution.
And good point to read documentation from start to end.