Why middleware not redirecting routes until hard refresh?
Unanswered
Holland Lop posted this in #help-forum
Holland LopOP
I have an authentication flow with Sign up, Login and Home page.
Sign up and Login pages should not be accessible after successful login. And after successful Login, the user redirects to Home page.
The problem is if I click back button in the browser, I'm going back to the Login page. But if I do a hard refresh there(in Login page) I get redirected to the Home page as expected and now even if I try to go back by clicking browser back button, it automatically redirects me to the Home page.
Why before hard reload I was able to go to Login page even though it is protected in middleware?
This is my middleware.
Any help would be much appreciated!
Sign up and Login pages should not be accessible after successful login. And after successful Login, the user redirects to Home page.
The problem is if I click back button in the browser, I'm going back to the Login page. But if I do a hard refresh there(in Login page) I get redirected to the Home page as expected and now even if I try to go back by clicking browser back button, it automatically redirects me to the Home page.
Why before hard reload I was able to go to Login page even though it is protected in middleware?
const publicRoutes = ["/login", "/signup"];
const isPublicRoute = publicRoutes.some((prefix) =>
request.nextUrl.pathname.startsWith(prefix)
);
if (session && isPublicRoute) {
const absoluteURL = new URL("/", request.nextUrl.origin);
return NextResponse.redirect(absoluteURL);
}
This is my middleware.
Any help would be much appreciated!
37 Replies
American Shorthair
I think the middleware runs only the first time you visit the page and then it gets cached in the router on the client side.
I am really not sure but what you can do is run router refresh after updating the session:
I had similar problem with next auth previously and this solved it.
I am really not sure but what you can do is run router refresh after updating the session:
function loginUser(){
// ...your login logic
router.refresh()
}
I had similar problem with next auth previously and this solved it.
Holland LopOP
Recently I tried a different thing:
This works with expected result. That is like replacing previous
So, the issue with credentials auth is fixed.
But the Google auth page issue still persist. The actual problem or something I'm not understanding is that, I use same component
if (typeof window !== "undefined" && window.history) {
window.history.replaceState(null, "", (window.location.href = "/"));
}
This works with expected result. That is like replacing previous
/login
route with /
or Home in the history.So, the issue with credentials auth is fixed.
But the Google auth page issue still persist. The actual problem or something I'm not understanding is that, I use same component
<GoogleAuth />
in Sign up page and Login page. As the Google auth work similarly for new users and existing users, it is supposed to work in a similar way in both from Sign up and Login page. But from Sign up page, it logs in the user and route to Home page and if I click back button, I will not go back to Sign up page. But the same component takes user back to Login page if <GoogleAuth />
this component from Login page is used.Same component behaves differently in different page. I'm not getting what is the actual issue causing this.
FYI: Google auth logics are in the
FYI: Google auth logics are in the
<GoogleAuth />
component.Holland LopOP
BUMP
Seems like you’re being a victim of Next.js hard cache behaviors lol. When you navigate back and forth you’re basically re-using the page from the existing cache and since the page isn’t running again or being requested again the auth check is skipped, that’s why when you refresh it does work, because you’re running the check again.
Try marking the pages as dynamic to see if that prevents the cached page
export const dynamic = “force-dynamic”;
export const dynamic = “force-dynamic”;
also what Next.js version you’re on? Next.js cache defaults and heuristic change between versions
Yea I believe that even dynamic pages have up to 30 seconds remaining cached in case you go back and forth to have an instant view instead of requesting again.
Here’s the Router Cache from version 14, this changed in version 15+.
https://nextjs.org/docs/14/app/building-your-application/caching#router-cache
Here’s the Router Cache from version 14, this changed in version 15+.
https://nextjs.org/docs/14/app/building-your-application/caching#router-cache
If you’re using a Server Action to log users in then you could call revalidatePath(“/the-path-you-wanna-purge/“) to clear the cache for that specific path and force the client to request the page again with the latest data instead of reusing the old version
Brown Booby
What's the most efficient way of guarding my endpoints in next.js app router
@luis_llanes Yea I believe that even dynamic pages have up to 30 seconds remaining cached in case you go back and forth to have an instant view instead of requesting again.
Here’s the Router Cache from version 14, this changed in version 15+.
https://nextjs.org/docs/14/app/building-your-application/caching#router-cache
Holland LopOP
Yes, you're right. I tried it and
"force-dynamic"
didn't worked.@luis_llanes If you’re using a Server Action to log users in then you could call revalidatePath(“/the-path-you-wanna-purge/“) to clear the cache for that specific path and force the client to request the page again with the latest data instead of reusing the old version
Holland LopOP
I'm not using Server Action, in that case where I can use
revalidatePath
? In the Login page itself or in the next route(in my case its home /
) to which a successful login routes?Cuz browser back button is creating the problem(allowing route to previous
/login
even if user already logged in) in my case.middleware only runs on hard refresh
if you set cookies in server action, it'll run again for next req
revalidatePath() /revalidateTag() is meant to use as a side-effect to an action and it’s meant to be used only on the Server Side, for example, after you did a mutation in a Server Action or route handler.
For client components you can use router.refresh() instead and this will also purge the cache
For client components you can use router.refresh() instead and this will also purge the cache
@luis_llanes revalidatePath() /revalidateTag() is meant to use as a side-effect to an action and it’s meant to be used only on the Server Side, for example, after you did a mutation in a Server Action or route handler.
For client components you can use router.refresh() instead and this will also purge the cache
Holland LopOP
I tried
Actually its an idiotic issue with this Next.js caching strategy.
router.refresh()
. But no hope.Actually its an idiotic issue with this Next.js caching strategy.
What’s the main issue you’re dealing with?
Next.js caching is kind of an extended topic and might bring lots of different issues
Next.js caching is kind of an extended topic and might bring lots of different issues
Holland LopOP
My current situation feels so crazy.
Scenario 1:
Currently I'm in Login page(
Scenario 2:
Currently I'm in Home page(
Analysing these 2 scenarios what I understand is that The issue is only happens when back button clicked, it works as expected when a forward button is clicked!
Scenario 1:
Currently I'm in Login page(
/login
) and successfully logged in and routed to Home page(/
). Now if I click browser back button I goes back to Login page. Now if I click forward button on browser, I can go forth and back until I hard reload in Login page(/login
), now it works as expected and redirect to /
(expected behavior).Scenario 2:
Currently I'm in Home page(
/
) and then navigate to Login page(/login
) and successfully logged in and routed to Home page(/
). Now if I click browser back button I goes back to Login page. [Change happens from here:] Now if I click back button again, I go back to Home page(/
) as I started from there. Now if I click forward button, which is to Login page(/login
), and now I don't see the Login page but instead redirect to Home page. Now everything works as expected!Analysing these 2 scenarios what I understand is that The issue is only happens when back button clicked, it works as expected when a forward button is clicked!
@luis_llanes What’s the main issue you’re dealing with?
Next.js caching is kind of an extended topic and might bring lots of different issues
Holland LopOP
Actual issue is, I should never see a Login page after a successful login.
Would be a lot of work to replicate your issue in my end, with the same Next.js versions so I could try and see what works and what doesn’t.
I wanna believe you tried all the stuff I’ve suggested, and if you did that might be all I can do to help sadly 😦
I wanna believe you tried all the stuff I’ve suggested, and if you did that might be all I can do to help sadly 😦
Catla
@Holland Lop I tried to replicate your issue but it is not working the way you pointed. On my side after successful login in if I go back to login page with back button, it still pushes me to the home page.
If it still does not work let me know.
@Catla <@483767130198900748> I tried to replicate your issue but it is not working the way you pointed. On my side after successful login in if I go back to login page with back button, it still pushes me to the home page.
Holland LopOP
Heya, first of all thanks a lot for you help. I appreciate your effort in trying to recreate the issue.
But in my case, I'm not using any Server Actions. The pages I mentioned, both Home page(
But in my case, I'm not using any Server Actions. The pages I mentioned, both Home page(
/
) and Login page(/login
) are SSR pages with export const dynamic = “force-dynamic”;
@luis_llanes Would be a lot of work to replicate your issue in my end, with the same Next.js versions so I could try and see what works and what doesn’t.
I wanna believe you tried all the stuff I’ve suggested, and if you did that might be all I can do to help sadly 😦
Holland LopOP
I understand. Thanks a lot for your replies and help!
@Catla <@483767130198900748> I tried to replicate your issue but it is not working the way you pointed. On my side after successful login in if I go back to login page with back button, it still pushes me to the home page.
Holland LopOP
And also, my Login page has two types of Login options, Google auth and Credentials auth. Credentials auth is working fine as expected. But the problem is only occurring when choosing Google auth.
@luis_llanes Would be a lot of work to replicate your issue in my end, with the same Next.js versions so I could try and see what works and what doesn’t.
I wanna believe you tried all the stuff I’ve suggested, and if you did that might be all I can do to help sadly 😦
Holland LopOP
@luis_llanes Is it okay if I DM you?
Holland LopOP
Just to share a live test link.
@luis_llanes Sure
Holland LopOP
Ok, thanks!
@Holland Lop Heya, first of all thanks a lot for you help. I appreciate your effort in trying to recreate the issue.
But in my case, I'm not using any Server Actions. The pages I mentioned, both Home page(`/`) and Login page(`/login`) are SSR pages with `export const dynamic = “force-dynamic”;`
Catla
I don't know your use case, but as of my understanding, I think your
/login
and /signup
page does not rely on any request time data, so instead of making them dynamic page with dynamic = "force-dynamic";
, it would be better generating them on build. So this way you don't have to generate the same page for every request, rather it will be generated once (on build) and be cached to CDN.@Holland Lop And also, my Login page has two types of Login options, Google auth and Credentials auth. Credentials auth is working fine as expected. But the problem is only occurring when choosing Google auth.
Catla
If your Credential auth is working fine, and the problem is with Google Auth, and if you are using
next-auth
, the next-auth
provides a default sign-in URL, i.e: http://localhost:3000/api/auth/signin?callbackUrl=yourURL
. You can check in middleware for this route (if the user is logged in or not) and redirect the user, like the previous way.