Skip to content
stoic man

Using Basic Auth middleware with Next.js

Simple, drop-in middleware for adding basic auth to your Next.js app

src/middleware.ts
import { NextResponse } from 'next/server'
import type { NextRequest } from 'next/server'
 
const VALID_USERNAME = process.env.VALID_USERNAME
const VALID_PASSWORD = process.env.VALID_PASSWORD
 
export const config = {
  matcher: '/dashboard/:path*'
}
 
function unauthorized(message: string = 'Unauthorized') {
  return new NextResponse(message, {
    status: 401,
    headers: {
      'WWW-Authenticate': 'Basic realm="Secure Area"',
      'Content-Type': 'application/json',
    },
  })
}
 
function badRequest(message: string = 'Bad Request') {
  return new NextResponse(message, {
    status: 400,
    headers: {
      'Content-Type': 'application/json',
    },
  })
}
 
export function middleware(request: NextRequest) {
  const authHeader = request.headers.get('Authorization')
 
  if (!authHeader) {
    return unauthorized('Authorization header is required')
  }
 
  const [scheme, credentials] = authHeader.split(' ')
 
  if (scheme !== 'Basic') {
    return badRequest('Invalid authentication scheme')
  }
 
  try {
    const [username, password] = Buffer.from(credentials, 'base64')
      .toString()
      .split(':')
 
    if (!username || !password) {
      return badRequest('Invalid credentials format')
    }
 
    if (username !== VALID_USERNAME || password !== VALID_PASSWORD) {
      return unauthorized('Invalid credentials')
    }
 
    // User is authenticated
    return NextResponse.next()
  } catch (error) {
    // Handle base64 decode errors
    return badRequest('Invalid credentials encoding')
  }
}