Guides
Next.js (Pages Router)

Next.js (Pages Router)

⚠️

This guide is for Next.js v13.4.20+ and above.

Middleware

Middleware enables you to add headers and generate nonces before the page renders.

Every time a page is viewed, a fresh nonce should be generated. This means that you must use dynamic rendering to add nonces.

 
import { NextRequest, NextResponse } from 'next/server'
import { generateNonce } from 'csp-toolkit/edge'
import { CSPPolicy, policyToString } from 'csp-toolkit'
 
export function middleware(request: NextRequest) {
    const nonce = generateNonce()
    const policy: CSPPolicy = {
        "default-src": ["'self'"],
        "script-src": ["'self'", `'nonce-${nonce}'`, "strict-dynamic"],
        "style-src": ["'self'",],
        "img-src": ["'self'", "blob:", "data:"],
        "font-src": ["'self'"],
        "object-src": ["'none'"],
        "base-uri": ["'self'"],
    } 
    const cspHeader = policyToString(policy)
 
    // Replace newline characters and spaces
    const contentSecurityPolicyHeaderValue = cspHeader
        .replace(/\s{2,}/g, ' ')
        .trim()
    
    const requestHeaders = new Headers(request.headers)
    requestHeaders.set('x-nonce', nonce)
    
    requestHeaders.set(
        'Content-Security-Policy',
        contentSecurityPolicyHeaderValue
    )
    
    const response = NextResponse.next({
        request: {
        headers: requestHeaders,
        },
    })
    response.headers.set(
        'Content-Security-Policy',
        contentSecurityPolicyHeaderValue
    )
    
    return response
}
 
 
 
 
export const config = {
    matcher: [
      /*
       * Match all request paths except for the ones starting with:
       * - api (API routes)
       * - _next/static (static files)
       * - _next/image (image optimization files)
       * - favicon.ico (favicon file)
       */
      {
        source: '/((?!api|_next/static|_next/image|favicon.ico).*)',
        missing: [
          { type: 'header', key: 'next-router-prefetch' },
          { type: 'header', key: 'purpose', value: 'prefetch' },
        ],
      },
    ],
  }
 

More information coming soon.