Next.js Discord

Discord Forum

Issue with Session Syncing Between Middleware and Frontend in Next.js

Answered
HEDI posted this in #help-forum
Open in Discord
Hello, I am new to Next.js and I would like to ask for your help with a problem I am facing.

Next.js version: 15.1.4
Iron-session version: 8.0.4

The issue is as follows:

I have a midmiddleware.ts file that does the following:
import { getSession } from '@/lib/service/session.service';
import { NextRequest, NextResponse } from 'next/server';

export const config = {
    matcher: ['/((?!api|_next/static|_next/image|favicon.ico).*)'],
};

export async function middleware(req: NextRequest) {
    const session = await getSession();
    if (!session.user) {
        console.log('create');
        session.user = 'test';
        await session.save();
        return NextResponse.next();
    } else {
        console.log('Delete');
        await session.destroy();
        return NextResponse.next();
    }
}

This works perfectly fine, I can see it in the dev console.

However, now I encounter an issue when I try to access it on the page:
import { getSession } from '@/lib/service/session.service';

export default async function Home() {
    const session = await getSession();

    return (
        <div>
            <h1>{session && session.user ? session.user : 'Not User'}</h1>
        </div>
    );
}

When there's a cookie, it always shows "Not User" even though there is one. When there is no cookie, it shows that there is a user.

The issue is that the session is not syncing properly. The middleware is working correctly because I can see the session being created and destroyed in the dev console, but the frontend always shows the old value. How can I fix this issue?
Answered by Giant Angora
Hi @HEDI

import { NextRequest, NextResponse } from 'next/server';
import { USER_COOKIE } from './constants';

export async function middleware(req: NextRequest) {
  const user = req.cookies.has(USER_COOKIE);

  //   delete existing cookie
  if (user) {
    console.log('Delete');

    const res = NextResponse.next();

    res.cookies.delete(USER_COOKIE);

    return res;
  }

  //   create new cookie
  if (!user) {
    console.log('create');

    const res = NextResponse.next();

    res.cookies.set(USER_COOKIE, JSON.stringify({ name: 'user' }), {
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'lax',
      path: '/',
      maxAge: 60 * 60 * 24 * 7,
    });

    return res;
  }
}
View full answer

54 Replies

up
Giant Angora
@HEDI maybe you have forgot to update cookie in middleware
But I can see it updated in the dev console, but on the first render, the frontend doesn't get the new data. However, on page change, I can see it in SPA mode; it just doesn't refresh immediately.
Giant Angora
could i ask for your session.save() code
import { getIronSession, SessionOptions } from 'iron-session';
import { cookies } from 'next/headers';

export const sessionOptions: SessionOptions = {
    cookieName: '_session',
    password: process.env.SESSION_SECRET as string,
    cookieOptions: {
        httpOnly: true,
        secure: process.env.NODE_ENV === 'production',
        sameSite: 'lax',
        path: '/',
        maxAge: 60 * 60 * 24 * 7,
    },
};

export const getSession = async () => {
    const session = await getIronSession<any>(await cookies(), sessionOptions);
    return session;
};


Irons session function .save
Giant Angora
okay
Giant Angora
Cookies can only be modified in a Server Action or Route Handler.
The middleware allows it because the modification happens.
Giant Angora
i dont use iron-session, does it save data in db?
It doesn't save anything, it generates cookies encrypted.
In the video, you can see what my issue is.
Giant Angora
i got it
there is very clear error
And what is it?
Giant Angora
wait... i am unsure... i need to test it
Okay, I will wait, my patience is like the sea.
Giant Angora
But this is not the error.
The error is that it perfectly saves the cookie to the dev console, but the frontend sees the previous state. However, if I navigate on the frontend, I can see the updated state. The cookie disappears because I told the middleware to do so. I tried to present this to show that the frontend always sees an older state.
see
this work
The issue is on the frontend, where it is one step behind. Of course, if I change the page, I can see the updated state, but during the first render, it is delayed.
But I already checked online, and in a 3-hour ChatGPT conversation, this is what it said.


Exactly! This behavior occurs because the middleware runs during request processing and modifies the cookie in the response, but SSR rendering is based on the cookies from the original request, as the middleware only affects the next request.

What happens exactly?

First request:
    The browser sends the current cookies (the old ones).
    The middleware runs, modifies or creates the cookie.
    The new cookie is only sent back to the browser as part of the HTTP Response.

SSR rendering:
    The Next.js SSR process starts after the middleware.
    The SSR process uses the cookies from the original request (the old ones).
    As a result, the SSR code does not see the new cookie state.

Response:
    The server sends the new cookies back in the response.
    The browser updates the cookies with the new value.

Next request:
    The browser sends the new cookies, so both the server and SSR can now see them.
`
Giant Angora
I saw source code of iron session and docs on nextjs
Nextjs docs have used cookies from req.cookies, they never used cookies function from next/headers in middleware
So you need to use getIronSession(req.cookeis) in middlewaser
Try it… @HEDI
okey i try
wait a second
Giant Angora
and use cookies function in server component from next/headers
…?
I think we should drop it because when I tried using req.cookies instead of Iron Session, the frontend still didn't update, only the dev console did. So clearly, the issue isn't with this, but rather that the data won't update immediately from SSR. As soon as I navigate, I can see the data, so the problem is something else, but I'll solve it in another way. So yes, I think we should close it.
Giant Angora
Sure
And also, Visual Studio is already showing an error that I started typing what you wrote.
Giant Angora
I am at mobile
You need to check
i see
Giant Angora
I will give it try after 6 ,7 hours
I am curious about it
As I said, from what I can see, the cookie is updated on the first render in the dev console, but the frontend only sees it when I navigate. Until I navigate, it doesn't see it.
Alright, if there are any developments, let me know. I’ll keep the post open so I can see what your outcome is, but regardless, I’ll solve it in another way.
Giant Angora
I can on make assumptions without try it… i will give you feedback in 6 7 hours
okey
If needed, I can provide the complete codebase on Git, which is my real code.
Giant Angora
I want to creat it from scratch and then we will compare
Oh, okay.
Giant Angora
Good night
It's almost morning for me, but good night!
Giant Angora
Its 6:39 am in Pakistan
I was working on ecommerce project late night
Oh, I see, it's currently 03:40 where I am.
Giant Angora
Hi @HEDI

import { NextRequest, NextResponse } from 'next/server';
import { USER_COOKIE } from './constants';

export async function middleware(req: NextRequest) {
  const user = req.cookies.has(USER_COOKIE);

  //   delete existing cookie
  if (user) {
    console.log('Delete');

    const res = NextResponse.next();

    res.cookies.delete(USER_COOKIE);

    return res;
  }

  //   create new cookie
  if (!user) {
    console.log('create');

    const res = NextResponse.next();

    res.cookies.set(USER_COOKIE, JSON.stringify({ name: 'user' }), {
      httpOnly: true,
      secure: process.env.NODE_ENV === 'production',
      sameSite: 'lax',
      path: '/',
      maxAge: 60 * 60 * 24 * 7,
    });

    return res;
  }
}
Answer
Giant Angora
@HEDI You cannot read a middleware-set cookie in a server component, route handler, or server action because the cookie is only set when the response is sent back. If you want to read the cookie after setting it, you must set it using next(). This means you cannot use iron-session in this case.