Next.js 14.0.4 - Browser Back Button Allows Access to Protected Routes After Logout

375 Views Asked by At

Description: I am using Next.js version 14.0.4 for a web application, and I'm facing an issue with browser navigation after a user logs out. Specifically, when a user logs out and clicks the browser back button, they can still access protected routes. However, if the user manually enters the protected route after logging out, the component does not render, and the middleware works fine.

import { NextResponse } from "next/server";

export default function middleware(req) {
    let verify = req.cookies.get("loggedin");
    let url = req.url;

    if (!verify && url.includes("/dashboard")) {
        return NextResponse.redirect("http://localhost:3000/");
    }

    if (verify && url === "http://localhost:3001/") {
        return NextResponse.redirect("http://localhost:3000/dashboard");
    }
}

Steps to Reproduce:

Log in to the application. Navigate to a protected route (e.g., "/dashboard"). Log out. Click the browser back button. Expected Behavior: The browser back button should not allow access to protected routes after the user logs out.

Actual Behavior: The browser back button allows access to protected routes after logout.

Additional Information:

Next.js version: 14.0.4 No error messages are being thrown in the console. The middleware appears to work as expected when manually entering protected routes after logout.

1

There are 1 best solutions below

7
Sakar On

This is a common issue with Single Page Applications (SPAs) like those built with Next.js, where the browser's cache and history allow users to see previously loaded pages using back button even after they've logged out.

To solve it, there are several ways:

  • Full page reload on logout : this can clear the state and ensure that client-side checks are re-run, this is a simple, though less elegant, solution that ensures your client-side authentication checks are performed again. To do that on logout function add the following

    window.location.href = '/login'; // or any other page
    
  • Cache control: Another solution is to set the cache control to no-store for your protected routes. This instructs the browser not to cache these pages.

    if (!verify && url.includes("/dashboard")) {
      response.headers.set("Cache-Control", "no-store");
      return NextResponse.redirect(new URL("/", req.url));
    }
    
  • Client side check implement client-side checks on your protected pages to verify if the user is still authenticated. If not, redirect them away from the page. This check should occur every time the page is rendered, not just on initial load.

    import { useEffect } from 'react';
    import { useRouter } from 'next/router';
    
    const ProtectedPage = () => {
      const router = useRouter();
      useEffect(() => {
          const verify = false; // replace false with cookie value for loggedin
          if (!verify) {
            router.push('/login');
          }
      }, []);
    
      // Rest of your component
    }