Search code examples
next.jsmiddlewarenext-authi18next

Next middleware combination - next-auth and next-international


I am trying to create a combined middleware for a next Js 14 application. In my case, I want to run the localization middleware for each route in the application. Also, I need to enable the authorization routes for some specific routes. but unfortunately, I could not make it a success. It gives me an error in localization middleware when redirected to the admin routes after a successful login.

Used packages and versions

"next-international": "^1.2.3", "next-auth": "^4.24.5",

Here is my code in middleware.ts

import { NextRequest, NextResponse, NextFetchEvent } from 'next/server';
import { NextRequestWithAuth, withAuth } from 'next-auth/middleware';

const I18nMiddleware = createI18nMiddleware({
  locales: ['en', 'sn'],
  defaultLocale: 'en',
  urlMappingStrategy: 'rewrite',
});

const nextAuthMiddleware = withAuth({
  pages: {
    signIn: '/login',
  },
});

export function middleware(
  request: NextRequest,
  requestAuth: NextRequestWithAuth,
  event: NextFetchEvent,
) {
  
  const nextAuthResponse = nextAuthMiddleware(request, event);

  if (request.nextUrl.pathname.startsWith('/admin')) {
    if (nextAuthResponse) {
      return nextAuthResponse;
    }
  }
  if (request.nextUrl.pathname.startsWith('/')) {
    return I18nMiddleware(request);
  }
  return NextResponse.next();
}

export const config = {
  matcher: [
    '/((?!api|static|.*\\..*|_next|favicon.ico|robots.txt).*)',
    '/',
    '/admin/:path*',
  ],
};```

Solution

  • It looks like there might be an issue with the way you're combining the two middleware functions. Instead of trying to use both nextAuthMiddleware and I18nMiddleware simultaneously, you should integrate the authentication check into the localization middleware.

    Here's how you can modify your middleware:

    import { NextRequest, NextResponse, NextFetchEvent } from 'next/server';
    import { withAuth } from 'next-auth/middleware';
    import { createI18nMiddleware } from 'next-international/middleware';
    
    const I18nMiddleware = createI18nMiddleware({
      locales: ['en', 'sn'],
      defaultLocale: 'en',
      urlMappingStrategy: 'rewrite',
    });
    
    const nextAuthMiddleware = withAuth({
      pages: {
        signIn: '/login',
      },
    });
    
    export async function middleware(request: NextRequest, event: NextFetchEvent) {
      // Check if the path starts with '/admin'
      if (request.nextUrl.pathname.startsWith('/admin')) {
        const authResponse = await nextAuthMiddleware(request, event);
    
        // Redirect to login page if user is not authenticated
        if (authResponse) {
          return authResponse;
        }
      }
    
      // Run localization middleware for all routes
      return I18nMiddleware(request);
    }
    
    export const config = {
      matcher: [
        '/((?!api|static|.*\\..*|_next|favicon.ico|robots.txt).*)',
        '/',
        '/admin/:path*',
      ],
    };
    

    In this code the authentication middleware is invoked only for routes starting with '/admin', and the localization middleware is applied to all routes.