Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Issue: Next js Middleware Ininite Redirection #371

Open
firstaxel opened this issue Dec 16, 2024 · 3 comments
Open

Issue: Next js Middleware Ininite Redirection #371

firstaxel opened this issue Dec 16, 2024 · 3 comments

Comments

@firstaxel
Copy link

i dont know the issue calling get authServer.getUser() in my nextjs middleware cause infinite redirection


import { authServer } from '@repo/auth/server';
import { type NextRequest, NextResponse } from 'next/server';

const middleware = async (request: NextRequest) => {
  // fetch the user object, and redirect if not logged in
  const user = await authServer.getUser();


  if (!user) {
    return NextResponse.redirect(new URL('/login', request.url));
  }

  // if (!user) {
  //   console.log(
  //     'User in middleware is not logged in. Redirecting to sign-in page'
  //   );
  //   return NextResponse.redirect(`${env.NEXT_PUBLIC_APP_URL}/login`);
  // }

  return new NextResponse('Authorized');
};

export default middleware;

export const config = {
  matcher: [
    // Skip Next.js internals and all static files, unless found in search params
    '/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)',
    // Always run for API routes
    '/(api|trpc)(.*)',
  ],
};

@firstaxel
Copy link
Author

@fomalhautb

@Mistes974
Copy link

Mistes974 commented Dec 17, 2024

@firstaxel Here is my working middleware and stack. I hope it will help.

export const stackServerApp = new StackServerApp({
  tokenStore: "nextjs-cookie",
  urls: {
    home: "/dashboard",
    signIn: "/auth/signin",
    afterSignIn: "/dashboard",
    afterSignOut: "/auth/signin",
  },
});

export async function middleware(request: NextRequest) {
  const user = await stackServerApp.getUser();
  const pathname = request.nextUrl.pathname;

  if (!user && pathname.startsWith("/auth")) {
    return NextResponse.next();
  }
  
  if (!user) {
    console.log("User not authenticated, redirecting to sign-in.");
    return NextResponse.redirect(
      new URL(stackServerApp.urls.signIn, request.url),
    );
  }

  return NextResponse.next();
}

export const config = {
  matcher: [
    // Exclure les routes Next.js et les fichiers statiques
    "/((?!_next|[^?]*\\.(?:html?|css|js(?!on)|jpe?g|webp|png|gif|svg|ttf|woff2?|ico|csv|docx?|xlsx?|zip|webmanifest)).*)",

    // Inclure les routes API et trpc
    "/(api|trpc)(.*)",
  ],
};

@dcayers
Copy link

dcayers commented Jan 1, 2025

@firstaxel The infinite loop you're running into is a direct result of the code you're writing. You have logic if NOT user THEN redirect, but nothing to check if you are on a protected page/route. Also, your matcher is actually matching against every path, except what you've listed -- it'll run on every route visit in your application.

So... when you visit / and you're not logged in, the middleware will redirect you to /login, which will then trigger the middleware to check if you are logged in, and redirects you to /login since you're not logged in, which then triggers the middleware to check if you are logged in, and redirects you to /login since you're not logged in. (see what I did there)

Here's what I'm doing in my middleware to redirect users to sign-in if they try to access a protected route when they aren't logged in:

import { stackServerApp } from "@repo/auth/server";
import { type NextRequest, NextResponse } from "next/server";

// This because Next.js doesn't let you match against route groups :(
const routeMaps = {
  protected: ["/dashboard", "/onboarding"],
  auth: ["/handler", "/sign-in", "/sign-up"],
};

export async function middleware(request: NextRequest) {
  const { pathname } = request.nextUrl;

  // Check if the user is authenticated
  const isAuthenticated = await checkAuthStatus();

  // Handle the base route
  if (pathname === "/") {
    if (isAuthenticated) {
      return NextResponse.redirect(new URL("/dashboard", request.url));
    } else {
      return NextResponse.redirect(new URL("/sign-in", request.url));
    }
  }

  if (routeMaps.auth.some((route) => pathname.includes(route))) {
    // If user is already authenticated and trying to access auth routes, redirect to dashboard
    if (isAuthenticated) {
      return NextResponse.redirect(new URL("/dashboard", request.url));
    }
    // Otherwise, allow access to auth routes
    return NextResponse.next();
  }

  if (routeMaps.protected.some((route) => pathname.includes(route))) {
    // If user is not authenticated and trying to access protected routes, redirect to login
    if (!isAuthenticated) {
      return NextResponse.redirect(new URL("/sign-in", request.url));
    }
    // Otherwise, allow access to protected routes
    return NextResponse.next();
  }

  // Handle other routes as needed
  return NextResponse.next();
}

 
// Check if the user is authenticated
async function checkAuthStatus(): Promise<boolean> {
  const user = await stackServerApp.getUser();

  if (user) {
    return true;
  }

  return false;
}

export const config = {
  matcher: [
    /*
     * Match all request paths except for the ones starting with:
     * - api (API routes)
     * - _next/static (static files)
     * - _next/image (image optimization files)
     * - favicon.ico, sitemap.xml, robots.txt (metadata files)
     */
    "/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)",
  ],
};

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants