import { NextResponse } from 'next/server'; function getValidUsers() { const users = {}; // Support multiple users format: "user1:pass1,user2:pass2" if (process.env.BASIC_AUTH_USERS) { const pairs = process.env.BASIC_AUTH_USERS.split(','); for (const pair of pairs) { const trimmed = pair.trim(); if (!trimmed) continue; // Split on first colon const colonIdx = trimmed.indexOf(':'); if (colonIdx !== -1) { const username = trimmed.slice(0, colonIdx).trim().toLowerCase(); const password = trimmed.slice(colonIdx + 1).trim(); if (username && password) { users[username] = password; } } } } // Fallback / Single user format: BASIC_AUTH_USER and BASIC_AUTH_PASSWORD if (process.env.BASIC_AUTH_USER && process.env.BASIC_AUTH_PASSWORD) { const username = process.env.BASIC_AUTH_USER.trim().toLowerCase(); const password = process.env.BASIC_AUTH_PASSWORD.trim(); if (username && password) { users[username] = password; } } return users; } export function middleware(req) { const basicAuth = req.headers.get('authorization'); const validUsers = getValidUsers(); // If any credentials are configured in ENV, enforce auth if (Object.keys(validUsers).length > 0) { if (basicAuth) { try { const authValue = basicAuth.split(' ')[1]; if (authValue) { const decoded = atob(authValue); const colonIdx = decoded.indexOf(':'); if (colonIdx !== -1) { const providedUser = decoded.slice(0, colonIdx).trim().toLowerCase(); const providedPwd = decoded.slice(colonIdx + 1); if (validUsers[providedUser] && validUsers[providedUser] === providedPwd) { return NextResponse.next(); } } } } catch (err) { // Ignore decoding errors and fall through to 401 } } // Return 401 Unauthorized if credentials don't match or are missing return new NextResponse('Auth required', { status: 401, headers: { 'WWW-Authenticate': 'Basic realm="Secure Area"', }, }); } // If no credentials are set in ENV, allow access return NextResponse.next(); } // Ensure the middleware only runs for paths that need protection. export const config = { matcher: [ /* * Match all request paths except for the ones starting with: * - _next/static (static files) * - _next/image (image optimization files) * - favicon.ico (favicon file) */ '/((?!_next/static|_next/image|favicon.ico).*)', ], };