Next.jsでHttpOnly CookieにJWTを安全に保存する
問題
JWTをlocalStorageに保存すると、XSS攻撃にそのまま晒されます。悪意のあるスクリプトがlocalStorage.getItem('token')でトークンを盗むことができます。
解決方法
// app/api/auth/login/route.ts
import { NextRequest, NextResponse } from 'next/server';
export async function POST(request: NextRequest) {
const { username, password } = await request.json();
const user = await authenticateUser(username, password);
if (!user) {
return NextResponse.json(
{ error: 'Invalid credentials' },
{ status: 401 }
);
}
const token = generateToken(user.id, user.username);
const response = NextResponse.json({ success: true, user });
// HttpOnly CookieにJWTを保存
response.cookies.set('auth-token', token, {
httpOnly: true, // JSからアクセス不可
secure: process.env.NODE_ENV === 'production', // HTTPSのみ
sameSite: 'lax', // CSRF防御
maxAge: 60 * 60 * 24, // 24時間
path: '/',
});
return response;
}
ポイント
httpOnly: trueが最も重要です。これを設定するとdocument.cookieでアクセスできなくなるため、XSS攻撃によるトークン窃取が不可能になります。secure: trueはプロダクション環境でのみ有効にすべきです。ローカル開発はHTTPのため、Cookieが送信されない問題が発生します。sameSite: 'lax'は他のサイトからのPOSTリクエスト時にCookieを送信しません。CSRF攻撃の基本的な防御線です。