Protected routes keep parts of your website safe. Middleware checks if a user can see a page before showing it.
Protected routes with middleware in NextJS
Start learning this pattern below
Jump into concepts and practice - no test required
or
Test this pattern10 questions across easy, medium, and hard to know if this pattern is strong
Introduction
Syntax
NextJS
import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; export function middleware(request: NextRequest) { const token = request.cookies.get('token')?.value; if (!token) { return NextResponse.redirect(new URL('/login', request.url)); } return NextResponse.next(); } export const config = { matcher: ['/protected-route', '/another-protected-route'], };
Middleware runs before the page loads to check conditions.
The matcher tells Next.js which routes to protect.
Examples
NextJS
export function middleware(request) { const isLoggedIn = Boolean(request.cookies.get('auth')); if (!isLoggedIn) { return NextResponse.redirect('/login'); } return NextResponse.next(); }
NextJS
export function middleware(request) { const role = request.cookies.get('role')?.value; if (role !== 'admin') { return NextResponse.redirect('/not-authorized'); } return NextResponse.next(); }
Sample Program
This middleware protects the '/dashboard' and '/settings' pages. If the user has no 'token' cookie, they get sent to '/login'. Otherwise, they can see the page.
NextJS
import { NextResponse } from 'next/server'; import type { NextRequest } from 'next/server'; export function middleware(request: NextRequest) { const token = request.cookies.get('token')?.value; if (!token) { return NextResponse.redirect(new URL('/login', request.url)); } return NextResponse.next(); } export const config = { matcher: ['/dashboard', '/settings'], };
Important Notes
Middleware runs on the server side before the page loads.
Cookies are a common way to check if a user is logged in.
Always test your middleware to avoid blocking public pages by mistake.
Summary
Middleware helps protect routes by checking user info before loading pages.
Use cookies or tokens to decide if a user can access a page.
Configure which routes to protect using the matcher setting.
Practice
1. What is the main purpose of middleware in Next.js when protecting routes?
easy
Solution
Step 1: Understand middleware role
Middleware runs before a page loads to control access or modify requests.Step 2: Identify protection purpose
In protected routes, middleware checks if a user is authenticated before allowing access.Final Answer:
To check user authentication before allowing access to certain pages -> Option AQuick Check:
Middleware protects routes by checking authentication [OK]
Hint: Middleware runs before page load to check user access [OK]
Common Mistakes:
- Thinking middleware styles pages
- Confusing middleware with database management
- Assuming middleware preloads images
2. Which of the following is the correct way to export middleware in Next.js to protect routes?
easy
Solution
Step 1: Recall Next.js middleware export syntax
Middleware must be exported as the default export function named middleware.Step 2: Check options for correct syntax
Only export default function middleware(req) { /* code */ } uses "export default function middleware(req)" which is valid syntax.Final Answer:
export default function middleware(req) { /* code */ } -> Option DQuick Check:
Middleware uses default export function [OK]
Hint: Middleware must be default exported as a function named middleware [OK]
Common Mistakes:
- Using named export instead of default
- Assigning middleware to a variable without export default
- Incorrect export statement syntax
3. Given this middleware code snippet, what happens when a user is not authenticated?
import { NextResponse } from 'next/server';
export default function middleware(req) {
const token = req.cookies.get('token');
if (!token) {
return NextResponse.redirect(new URL('/login', req.url));
}
return NextResponse.next();
}medium
Solution
Step 1: Analyze token check in middleware
The middleware checks if the 'token' cookie exists; if not, it triggers a redirect.Step 2: Understand redirect behavior
If no token, middleware returns a redirect response to '/login' page.Final Answer:
The user is redirected to the /login page -> Option BQuick Check:
No token causes redirect to login [OK]
Hint: No token cookie means redirect to login page [OK]
Common Mistakes:
- Assuming user stays on page without token
- Thinking middleware throws error on missing token
- Confusing redirect target URL
4. Identify the error in this middleware code that aims to protect routes:
import { NextResponse } from 'next/server';
export default function middleware(req) {
const token = req.cookies.token;
if (!token) {
return NextResponse.redirect('/login');
}
return NextResponse.next();
}medium
Solution
Step 1: Check cookie access method
In Next.js middleware, cookies are accessed with req.cookies.get('token'), not req.cookies.token.Step 2: Verify redirect usage
Redirect can accept a relative path, so that is valid here.Final Answer:
Accessing cookies incorrectly; should use req.cookies.get('token') -> Option CQuick Check:
Use req.cookies.get('token') to read cookies [OK]
Hint: Use req.cookies.get('token') to read cookies in middleware [OK]
Common Mistakes:
- Using dot notation for cookies object
- Thinking redirect URL must be absolute
- Confusing NextResponse.next() with continue()
5. You want to protect only the routes starting with
/dashboard using middleware. Which is the correct way to apply middleware only to these routes?hard
Solution
Step 1: Understand matcher pattern syntax
The matcher uses path patterns where ':path*' matches all subpaths under /dashboard.Step 2: Compare options for correct pattern
export const config = { matcher: ['/dashboard/:path*'] }; uses '/dashboard/:path*' which correctly matches /dashboard and all nested routes.Final Answer:
export const config = { matcher: ['/dashboard/:path*'] }; -> Option AQuick Check:
Use '/dashboard/:path*' to match dashboard and subpaths [OK]
Hint: Use ':path*' to match all subpaths under a route [OK]
Common Mistakes:
- Using wildcard * without colon for subpaths
- Matching only exact /dashboard without subpaths
- Using invalid glob pattern like /**
