typescriptadvanced

Authentication Middleware with Session Check

Protect routes with middleware that validates session tokens and redirects unauthenticated users.

typescript
// middleware.ts
import { NextRequest, NextResponse } from 'next/server';

const PUBLIC_PATHS = [
  '/',
  '/login',
  '/register',
  '/forgot-password',
  '/api/auth',
];

function isPublicPath(pathname: string): boolean {
  return PUBLIC_PATHS.some(
    (path) => pathname === path || pathname.startsWith(`${path}/`)
  );
}

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

  // Skip static files and public paths
  if (
    pathname.startsWith('/_next') ||
    pathname.includes('.') ||
    isPublicPath(pathname)
  ) {
    return NextResponse.next();
  }

  // Check for session token
  const token = request.cookies.get('session-token')?.value;

  if (!token) {
    const loginUrl = new URL('/login', request.url);
    loginUrl.searchParams.set('callbackUrl', pathname);
    return NextResponse.redirect(loginUrl);
  }

  // Validate token (call your auth service)
  try {
    const res = await fetch(`${request.nextUrl.origin}/api/auth/validate`, {
      headers: { Authorization: `Bearer ${token}` },
    });

    if (!res.ok) {
      const loginUrl = new URL('/login', request.url);
      loginUrl.searchParams.set('callbackUrl', pathname);
      const response = NextResponse.redirect(loginUrl);
      response.cookies.delete('session-token');
      return response;
    }

    // Attach user info to headers for downstream use
    const user = await res.json();
    const requestHeaders = new Headers(request.headers);
    requestHeaders.set('x-user-id', user.id);
    requestHeaders.set('x-user-role', user.role);

    return NextResponse.next({ request: { headers: requestHeaders } });
  } catch {
    return NextResponse.next();
  }
}

export const config = {
  matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
};

Use Cases

  • route protection
  • session validation
  • role-based access

Tags

Related Snippets

Similar patterns you can reuse in the same workflow.