Next.js Discord

Discord Forum

Middleware with next-auth and next-intl

Unanswered
MeKa posted this in #help-forum
Open in Discord
In Middleware, if there is a user login, I want to close (direct) the login to the "login", "register" pages. And if the user role is "Admin", he can enter the /admin page.
import { NextRequest } from "next/server";
import { withAuth } from "next-auth/middleware";
import createIntlMiddleware from "next-intl/middleware";

const locales = ["tr", "en"];
const AUTH_PAGES = ["/login", "/register"];

const intlMiddleware = createIntlMiddleware({
  locales,
  defaultLocale: "tr",
});

const authMiddleware = withAuth((req) => intlMiddleware(req), {
  callbacks: {
    authorized: ({ token }) => token != null,
  },
  pages: {
    signIn: "/login",
  },
});

export default function middleware(req: NextRequest) {
  const { url, nextUrl, cookies } = req;

  const publicPathnameRegex = RegExp(
    `^(/(${locales.join("|")}))?(${AUTH_PAGES.join("|")})?/?$`,
    "i"
  );
  const isPublicPage = publicPathnameRegex.test(nextUrl.pathname);

  if (isPublicPage) {
    return intlMiddleware(req);
  } else {
    return (authMiddleware as any)(req);
  }
}

export const config = {
  // Skip all paths that should not be internationalized
  matcher: ["/((?!api|_next|.*\\..*).*)"],
};

34 Replies

You can't put your access pages behind an authentication middleware. How is anybody supposed to login to your website?
If the user is logged in, it is absurd to continue to enter the "login page" again
AUTH_PAGES should really be PROTECTED_PAGES and contain stuff like "dashboard" or other pages that unauthenticated viewers can't access.

Your login and register pages need to be accessible at all times.
If the user is not logged in, the "login" page may be open.
Yeah, but that's not what you're doing here...
It got complicated as "next-intl" is included and I'm looking for ideas on how to solve it.
You're completely closing /login from being accessed, even for unauthenticated users...
No, they're both open and I can log in to both, even though I'm logged in. Even though I'm not logged in, I can still login 😄
Not Signed In
Signed in
Sorry, I read it completely wrong...
To redirect authenticated users to your home page when they visit /login you can use getServerSession like this:

/app/login/page.tsx
import { redirect } from 'next/navigation'
import { getServerSession } from "next-auth/next"
import { authOptions } from "../api/auth/[...nextauth]/route"

export default async function LoginPage() {
  const session = await getServerSession(authOptions)

  if (session) {
    redirect('/')
  }

  return <div>Login</div>
}
I know this but it's not a clear solution for me. Shouldn't be impossible with middleware
The user enters, if there is no token, the login is provided, if there is a token, the redirect is made.
What's not clear about it? You get the session. If it's there redirect, and if not render the page. It's as simple as that
However, if he enters the page, if there is a session, he will be redirected. Even for seconds, the user sees this blank side.
It is a problem that the page appears blank during the session control process.
@MeKa It is a problem that the page appears blank during the session control process.
Black carp
How much sec it appears blank? It will hardly take a sec for redirect as this is done server side
@MeKa did you tried the method?
@Black carp How much sec it appears blank? It will hardly take a sec for redirect as this is done server side
I didn't try server side as there is 'use client' in the file. Client side can be 1 second or less.
Black carp
Middleware file is complete server side process
@Black carp Middleware file is complete server side process
Sir, with next-intl it became difficult. It's easier with middleware whether or not 'use client'.
Even if you use 'use client', it won't come up for control checks before in middleware.
I got "build". and it goes to /login page, shows everything and redirects in seconds. but I can see the input and buttons.
@MeKa I didn't try server side as there is 'use client' in the file. Client side can be 1 second or less.
Your login page should be a server component so that the redirection is as fast as possible and is done on the server. Then inside it you can nest as many client components as you want.
If you make it a client component it will show everything until the user gets redirected
Black carp
Otherwise u can show a loader on page if there is no token and eventually it will redirect
Page does not go with Server Components.
@MeKa Page does not go with Server Components.
Black carp
By default everything is server component unless if you want to use any hooks
So how can I restrict the /admin route?

role: User, Admin
const PROTECTED_PAGES = [ "/admin"];