vercel / next.js

The React Framework
https://nextjs.org
MIT License
123.5k stars 26.35k forks source link

NextJs 14 middleware redirect issue: User Keeps getting redirected to /login after successful Sign-In #59218

Open anni1236012 opened 7 months ago

anni1236012 commented 7 months ago

Link to the code that reproduces this issue

https://github.com/anni1236012/nextjsMiddleware

To Reproduce

  1. yarn dev
  2. All pages are protected via middleware except home page.
  3. Click on any link other than home page and it should redirect you to /login.
  4. Now click on login and it will set the sessionToken cookie with value "loggedin". At this stage, user is authenticated and it should allow users to see the protected pages.
  5. Now click on any protected page and you will see the /login page which is not the expected behavior. It should show the protected page immediately after the successful signin. However, it does work after a few seconds and user can see the protected page. I don't know why there is a delay.

https://github.com/vercel/next.js/assets/86418669/67bb7e52-b6a3-41c0-b4ad-3eed1eff8404

Current vs. Expected behavior

Delayed navigation, looks like all requests are not reaching middleware and served from cache.

Verify canary release

Provide environment information

Operating System:
  Platform: linux
  Arch: x64
  Version: #38~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Nov  2 18:01:13 UTC 2
Binaries:
  Node: 20.5.1
  npm: 9.8.0
  Yarn: 1.22.19
  pnpm: N/A
Relevant Packages:
  next: 14.0.4-canary.37
  eslint-config-next: 14.0.3
  react: 18.2.0
  react-dom: 18.2.0
  typescript: 5.3.2
Next.js Config:
  output: N/A

Which area(s) are affected? (Select all that apply)

Middleware / Edge (API routes, runtime)

Additional context

No response

SuhelMakkad commented 7 months ago

@anni1236012 try setting the status code to 303. One of the reasons it might fail is because of the browser cache. By default NextResponse.redirect will do a 307, which can be cahced by the browser.

return NextResponse.redirect(new URL("/login", request.url), {
    status: 303,
});
anni1236012 commented 7 months ago

@SuhelMakkad it did not change the behavior.

SuhelMakkad commented 7 months ago

Interesting 🤔 I am using this exact setup for my app and it works fine. I tried your repo on my local machine, and after the changes it worked. Maybe you need to clear your browser cache.

yasermazlum commented 7 months ago

I have exactly the same problem, it does not give the expected behaviour for a while

anni1236012 commented 7 months ago

I fixed it with rewrite instead of redirect.

return NextResponse.rewrite(new URL("/login", request.url), {
        status: 303,
      });
yasermazlum commented 7 months ago

@anni1236012 no, the problem is not solved. a short time still does not give the expected result

anni1236012 commented 7 months ago

@yasermazlum Please share your github link to recreate the issue.

babpulss commented 6 months ago

try to avoid loading cached page append random query on querystring ex) localhost:3000/hello=${Date.now()}

cyb3rsalih commented 2 months ago

I also stucked at login page, when I debug see that The user object found and returns true response. But the status code is 303

pedroSoaresll commented 1 month ago

At NextJS 15 (canary version) it was fixed, the server middleware is correct changing the browser URL after NextResponse.redirect.

But I guess I found another error when passing a hash parameter /some-url#value-here, the hash parameter is not sending with the redirected URL.

The problem was not completely fixed.

skychavda commented 2 weeks ago

I am experiencing an issue with the middleware. I need to route the user based on their role, but the middleware is not able to route properly. Here's the explanation:

I have two roles in my app, manager and staff, and a user can have either of these roles in their respective org.

When the user changes the org using a dropdown in the UI, the middleware is supposed to detect the new selected org and route the user to the corresponding URL. I've written the following logic for this:

if (orgRole === 'manager' && request.nextUrl.pathname.includes('/staff')) {
      const url = request.nextUrl.clone()
      url.pathname = `${orgShortId}/dashboard/manager/app`
      return NextResponse.redirect(url, { status: 303 })
    }

    if (orgRole === 'staff' && request.nextUrl.pathname.includes('/manager')) {
      const url = request.nextUrl.clone()
      url.pathname = `${orgShortId}/dashboard/staff/app`
      return NextResponse.redirect(url, { status: 303 })
    }

However, the issue I'm facing is that the app is not getting routed to the URL as expected; it remains unchanged.

JohnHuang-CT commented 1 week ago

might need to use router.refresh