「ユーザー登録機能を実装したはずなのに、なぜかエラーが...」
認証機能のテストで test+admin@gmail.com
、user+dev@example.com
のようなGmail+エイリアス(+記号付きメール)を使ったことはありませんか?この便利な機能は、1つのメールアドレスで複数のテストユーザーを作れる開発者の強い味方ですが、実は多くの認証システムで弾かれてしまいます。
Next.js認証システムでよく遭遇する4つのエラーと解決法を、実際のログと解決過程で解説。Gmail+エイリアス対応から開発環境設定まで、再発防止の方法も紹介します。
解決できるエラー: Gmail+エイリアス対応、JWT二重検証、bcryptパスワード比較、Edge Runtime制約
🚨 エラー1: Gmail+エイリアス対応のメールバリデーションエラー
症状: user+alias@gmail.com
で Validation error: Invalid email format
🔍 原因: /^\w+([.-]?\w+)*@\w+([.-]?\w+)*(\.\w{2,3})+$/
の \w
が +
記号を含まない
💡 正規表現とは?
文字のパターンを決めるルールです。「メールアドレスはこんな形でないとダメ」という条件を文字で表現したもの。\w
は「文字・数字・アンダーバー」のみ許可するため、+
記号が弾かれてしまいます。
✅ 解決策:
match: /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/
💡 RFCとは?
RFC(Request for Comments)は、インターネットの公式ルールブック。メールアドレスの正しい形を決めた国際基準で、この基準に従うと世界中で通用するメールアドレス判定ができます。
🛡️ 予防策: RFC準拠のバリデーション、Gmail+エイリアステスト必須
🚨 エラー2: JWT二重検証による「無効な認証トークン」エラー
症状: メール認証リンククリック後、必ず /auth/verify-error
にリダイレクト
💡 JWTとは?
JWT(JSON Web Token)は、デジタルの身分証明書のようなもの。コンサートの入場券に偽造防止の印鑑が押してあるのと同じで、この印鑑(署名)を確認するだけで本物だとわかります。そのため、わざわざ券売所に電話して確認する必要がありません。
🔍 原因: jwt.verify()
後にDB照合も実行する二重検証が失敗原因
// 問題:JWTは自己完結型なのにDB照合も実行
jwt.verify(token, process.env.JWT_SECRET!);
if (user.emailVerificationToken !== token) { // ←これが不要
✅ 解決策:
try {
jwt.verify(token, process.env.JWT_SECRET!);
// JWTが検証済みなので、DB照合不要
user.emailVerified = true;
await user.save();
} catch (error) {
return NextResponse.redirect(new URL('/auth/verify-error', req.url));
}
🛡️ 予防策: JWTの自己完結性理解、「シンプル=安全」原則
🚨 エラー3: bcryptパスワード比較の謎の失敗
症状: 正しいパスワードでも bcrypt.compare result: false
💡 bcryptとは?
bcryptは、パスワードを暗号に変える一方通行のシステムです。例えば「abc123」を「$2b$12$xyz...」という暗号に変換し、元のパスワードは取り出せません。ログイン時は、入力されたパスワードを同じ方法で暗号化して結果を比較します。設定が違うと同じパスワードでも異なる暗号になってしまいます。
🔍 原因: 登録時とログイン時のハッシュ化処理に不一致
✅ 解決策:
// 正しいハッシュを再生成してDB更新
const newHash = await bcrypt.hash('testpass123', 12);
await User.findByIdAndUpdate(userId, { password: newHash });
🛡️ 予防策: saltラウンド数統一(12推奨)、処理の一貫性確保
🚨 エラー4: Edge Runtime暗号化モジュールエラー
症状: The edge runtime does not support Node.js 'crypto' module
💡 Edge Runtimeとは?
Edge Runtimeは、軽量で高速な実行環境です。通常のNode.js環境と比べて、必要最小限の機能のみを搭載することで、世界中のどこにでも素早く配置でき、ユーザーに近い場所で超高速に動作します。ただし、一部の重い機能(cryptoモジュールなど)は利用できません。
🔍 原因: NextAuth + middleware.ts で Edge Runtime制約に抵触
✅ 解決策:
// JWTセッション戦略に変更
export default {
session: { strategy: "jwt" },
// adapter: MongoDBAdapter(clientPromise), // 削除
}
🛡️ 予防策: Edge Runtime制約事前調査、JWTセッション優先採用
認証システム設計の鉄則
- シンプル性の原則 - 複雑な認証フローほどバグの温床。不要な検証処理は削除
- 一貫性の確保 - ハッシュ化、環境変数、エラーハンドリングで統一ルール適用
- 環境制約の理解 - Edge Runtime、NextAuth、MongoDBの制約を事前把握
- 段階的なデバッグ - 複数エラー時は一つずつ解決、根本原因を特定
実践チェックリスト + 開発環境活用法
即使える認証実装チェックリスト
- メールバリデーションがGmail+エイリアス対応済み
- JWT検証とDB照合の重複がない
- bcryptのsaltラウンド数が統一されている
- Edge Runtime制約に配慮した設計になっている
- 環境変数(JWT_SECRET、SMTP設定)が正しく設定されている
開発環境で認証エラーを未然に防ぐ設定
これらのエラーを二度と起こさないために、Claude CodeやCursorに以下のプロンプトを設定しておくことを強くおすすめします:
CLAUDE.mdやCursorのrulesに追加
# 認証システム実装チェック
## JWT実装時の必須確認
- JWT検証とDB照合の二重チェックを避ける
- JWT_SECRET環境変数の設定確認
- トークン有効期限の適切な設定
## メール認証実装時の必須確認
- RFC準拠の正規表現使用(Gmail+エイリアス対応)
- SMTP設定の環境変数確認
- 絶対URL生成の一元化
## パスワード処理の必須確認
- bcryptハッシュ化の一貫性
- 登録時とログイン時の処理統一
- saltラウンド数の適切設定(12推奨)
## Edge Runtime制約確認
- crypto モジュール使用箇所のチェック
- middleware.tsでのNextAuth利用回避
- JWTセッション戦略への移行検討
自動化のメリット
認証機能実装時に自動的にチェックポイントが提示され、同じエラーの再発を防げます。開発時間の短縮と品質向上を同時に実現できる、初心者には特におすすめの方法です。
まとめ
Next.js認証システムの4つのエラーと解決法を紹介しました:
- RFC準拠のバリデーション - メール形式問題を回避
- JWTの特性理解 - 二重検証の罠を避ける
- 一貫したハッシュ化処理 - パスワード比較エラーを防ぐ
- Edge Runtime制約の把握 - 適切な技術選択
開発環境のプロンプト設定で、エラー再発防止と学習効果を向上させましょう。今回の解決法とチェックリストで、堅牢な認証システムを構築してください。