DEV Community

Cover image for Implementing Authentication Middleware in Next.js with i18n Support
Tajudeen Abdulgafar
Tajudeen Abdulgafar

Posted on

Implementing Authentication Middleware in Next.js with i18n Support

Introduction

Building secure web applications requires implementing proper authentication and authorization mechanisms. In Next.js applications, middleware provides an excellent way to protect routes and handle authentication before requests reach your pages. This blog post will walk you through implementing a robust authentication middleware that seamlessly integrates with internationalization (i18n) routing for library_proj, one of the project I contributed to doing the hacktoberfest.

Why Authentication Middleware?

Authentication middleware sits between the client request and your application logic, allowing you to:

  • Protect routes before they're rendered
  • Redirect unauthenticated users to login pages
  • Preserve intended destinations with redirect parameters
  • Prevent authenticated users from accessing auth pages
  • Centralize authentication logic for better maintainability

By handling authentication at the middleware level, you ensure security checks happen early in the request lifecycle, before any server-side rendering or data fetching occurs.

Architecture Overview

The authentication middleware works in conjunction with Next.js App Router and includes:

Request → Middleware → Authentication Check → Route Protection → i18n Routing → Response
Enter fullscreen mode Exit fullscreen mode

The middleware performs these checks in order:

  1. Extract locale from the pathname or browser preferences
  2. Check authentication status via cookies
  3. Determine route type (public vs. protected)
  4. Apply redirects based on authentication state
  5. Handle locale routing for proper i18n support

Implementation Details

Authentication Check

The middleware checks for authentication tokens stored in cookies. It supports multiple token types for flexibility:

function isAuthenticated(request: NextRequest): boolean {
  const authToken = request.cookies.get('auth_token');
  const sessionToken = request.cookies.get('session_token');

  // Check for either auth_token or session_token
  return !!(authToken || sessionToken);
}
Enter fullscreen mode Exit fullscreen mode

Route Classification

The middleware distinguishes between public and protected routes:

Public Routes

Routes accessible without authentication:

  • /login
  • /signup
  • /register
  • /forgot-password
  • /reset-password

Protected Routes

By default, all routes are protected except those explicitly marked as public. This includes:

  • Dashboard routes (/, /my_books, /books)
  • Profile and settings pages
  • Any other application routes

Protection Logic

function isProtectedRoute(pathname: string): boolean {
  const pathWithoutLocale = getPathnameWithoutLocale(pathname);

  // If it's a public route, it's not protected
  if (isPublicRoute(pathname)) {
    return false;
  }

  // All other routes are protected by default
  return true;
}
Enter fullscreen mode Exit fullscreen mode

This "secure by default" approach ensures that new routes are automatically protected unless explicitly added to the public routes list.

Key Features

1. Automatic Route Protection

All routes are protected by default, reducing the risk of accidentally exposing sensitive pages.

2. Smart Redirects

  • Unauthenticated users accessing protected routes are redirected to /login with a redirect parameter
  • Authenticated users accessing auth pages (login, signup) are redirected to the home page
  • Locale is preserved in all redirects

3. i18n Integration

The middleware seamlessly handles internationalization:

  • Extracts locale from pathname
  • Preserves locale during redirects
  • Works with browser language preferences

4. Server Component Support

Authentication status is exposed via headers for server components:

response.headers.set('x-authenticated', authenticated ? 'true' : 'false');
Enter fullscreen mode Exit fullscreen mode

Server components can access this header to conditionally render content:

// In a server component
const headers = await headers();
const isAuthenticated = headers.get('x-authenticated') === 'true';
Enter fullscreen mode Exit fullscreen mode

Best Practices

1. Secure Cookie Settings

When setting authentication cookies, use secure settings:

// In your login handler
cookies().set('auth_token', token, {
  httpOnly: true,    // Prevent XSS attacks
  secure: process.env.NODE_ENV === 'production', // HTTPS only in production
  sameSite: 'lax',   // CSRF protection
  maxAge: 60 * 60 * 24 * 7, // 7 days
  path: '/',
});
Enter fullscreen mode Exit fullscreen mode

2. Token Validation

For production, consider validating tokens server-side:

async function isAuthenticated(request: NextRequest): Promise<boolean> {
  const token = request.cookies.get('auth_token')?.value;
  if (!token) return false;

  try {
    // Validate token with your backend
    const response = await fetch(`${BACKEND_URL}/api/auth/verify`, {
      headers: { Authorization: `Bearer ${token}` }
    });
    return response.ok;
  } catch {
    return false;
  }
}
Enter fullscreen mode Exit fullscreen mode

3. Error Handling

Add proper error handling for edge cases:

try {
  // Middleware logic
} catch (error) {
  console.error('Middleware error:', error);
  // Fallback: allow request but log error
  return NextResponse.next();
}
Enter fullscreen mode Exit fullscreen mode

4. Testing

Test your middleware with different scenarios:

  • ✅ Unauthenticated user accessing protected route → redirects to login
  • ✅ Authenticated user accessing login → redirects to home
  • ✅ Authenticated user accessing protected route → allowed
  • ✅ Locale preservation during redirects
  • ✅ Public routes accessible without authentication

Conclusion

Implementing authentication middleware in Next.js provides a robust, centralized way to protect your application routes. By combining authentication checks with i18n routing, you create a seamless user experience that works across different languages and locales.

Top comments (0)