🔖

自作の認証よりもNextAuth.js などの実績あるライブラリの方が安全か?

に公開

今作っているプロダクトについて、自作の認証を入れましたが、NextAuth.js などの実績あるライブラリの方が有効かどうか、検討した結果をメモします🙏

本プロジェクトの認証の概要

方式: メールアドレス + パスワード による認証で、ログイン後に JWT(アクセス+リフレッシュ)HttpOnly Cookie に乗せてセッション管理しています。Bearer トークンでの API 認証にも対応しています。


パスワード漏洩リスクに対する対策

1. パスワードの保存(平文は保存していない)

  • bcrypt でハッシュ化した値のみを DB に保存しています(lib/auth.ts)。
  • ラウンド数は 12BCRYPT_ROUNDS = 12)で、一般的な強度として問題ない水準です。
  • DB の User モデルには passwordHash のみがあり、平文パスワードは保存していません(prisma/schema.prisma)。
36:lib/auth.ts
export async function hashPassword(password: string): Promise<string> {
  return bcrypt.hash(password, BCRYPT_ROUNDS);
}

export async function verifyPassword(
  password: string,
  hash: string
): Promise<boolean> {
  return bcrypt.compare(password, hash);
}
  • 登録時・パスワードリセット時も、いずれも hashPassword を通したハッシュだけを保存しています(app/api/auth/register/route.ts, app/api/auth/reset-password/confirm/route.ts)。

2. パスワード強度のチェック

  • 8文字以上かつ英字と数字の両方を含むことを必須にしています(lib/auth.tsvalidatePasswordStrength)。
  • 登録・パスワード変更の両方でこのチェックを実行しています。

3. ログへのパスワード出力

  • 認証系 API の catch では console.error('[login]', e) のように 例外オブジェクト e のみをログに出しており、リクエストボディ(パスワード)はログに含めていません。平文パスワードがログに流れる実装にはなっていません。

4. セッション(Cookie)の設定

  • 認証用 Cookie は HttpOnly のため、JavaScript から参照できず XSS でトークンを読まれにくい設計です。
  • 本番では Secure が有効(NODE_ENV === 'production')で、HTTPS 前提です。
  • SameSite: 'lax' により、基本的な CSRF リスクを抑えています。

5. メール認証

  • 登録後、メール認証が完了するまでログイン不可です(app/api/auth/login/route.tsemailVerified をチェック)。
  • 認証用トークンは randomBytes(32).toString('hex') で生成し、有効期限付きで管理しています。

6. パスワードリセット

  • リセット用トークンも randomBytes(32).toString('hex') で生成し、24時間の有効期限を設けています。
  • リセット完了後にトークンと有効期限を null にして無効化しています(二度使い防止)。

7. ログイン失敗時のメッセージ

  • 「メールアドレスまたはパスワードが正しくありません」のように、ユーザー存在の有無を区別しない文言で返しており、ユーザー列挙を抑えています。

環境・運用で気にしたい点

  • JWT_SECRET: lib/auth.ts で「32文字以上必須」とチェックしています。推測困難で長い秘密鍵を本番で設定し、漏洩しないよう管理する必要があります。
  • HTTPS: 本番では Cookie の secure が true になるため、HTTPS の運用が前提です。
  • レート制限: ログイン・パスワードリセットなどに対するレート制限はコード上は見当たりません。ブルートフォースやリセットメール濫用対策として、リバースプロキシやアプリ層での制限を検討するとよいです。

現在の実装まとめ

  • パスワードは 平文では保存・ログ出力しておらず、bcrypt ハッシュのみを扱っています。
  • セッションは HttpOnly / Secure(本番) / SameSite が設定された JWT Cookie で管理されています。
  • メール認証・パスワードリセットはトークン+有効期限で制御されています。

設計としては、パスワード漏洩を抑えるための一般的な対策(ハッシュ化・強度チェック・ログに載せない・Cookie の安全な設定)は取り入れられています。運用では JWT_SECRET の管理 と、必要に応じた レート制限の追加 を検討するとよいです。


結論から言うと、「より安全か」は目的次第です。

  • **パスワードの扱い(漏洩リスク)**については、現状の自前実装でも NextAuth.js に乗り換えても大きな差はありません
  • 実装の実績・運用面・OAuth 利用を考えると、NextAuth.js を検討する価値はあります

以下、整理して説明します。


1. パスワードまわりは「ライブラリで変わるか」

NextAuth.js の Credentials プロバイダー を使う場合でも、

  • パスワードのハッシュ化・照合
  • DB への保存・取得

自分で書くか、別ライブラリに任せる形になります。NextAuth が「パスワードを安全に保存してくれる」わけではありません。

そのため、

  • 平文パスワードを保存しない
  • bcrypt などでハッシュ化する
  • ログにパスワードを出さない

といった点は、今の自前実装でも NextAuth 導入後も、ほぼ同じ責任で実装することになります。
「パスワード漏洩リスク」だけを見ると、「NextAuth にすれば自動で安全」にはなりません。


2. NextAuth.js を使うと「安全になりやすい」部分

NextAuth.js の利点は、主に 認証フロー全体の実績と、自分で書かなくてよい部分 にあります。

観点 自前実装 NextAuth.js
セッション・Cookie の設計 自分で設計・検証が必要 多くの環境で使われた形が用意されている
CSRF 対策 自分でトークン等を用意 組み込みの CSRF 保護
セッション固定など 自前で考慮が必要 ライブラリ側である程度カバー
セキュリティ修正 自前で追いかけが必要 メンテナンス・パッチに乗れる
OAuth(Google/GitHub 等) 自前実装は手間・ミスが増えやすい プロバイダー追加が容易

つまり、

  • 「パスワードの保存・照合」の安全性 → 今の実装でも NextAuth でも、設計次第でどちらも安全にできる。
  • 「認証フロー・セッション・OAuth」の安全性・手間 → NextAuth の方が、実績と手間の面で有利になりやすい。

3. このプロジェクトの現状をどう見るか

いまの実装は、

  • bcrypt(ラウンド 12)
  • HttpOnly / Secure / SameSite の Cookie
  • 平文パスワードを保存・ログに出していない
  • メール認証・パスワードリセットのトークン管理

といった点で、一般的なベストプラクティスに沿っています
「自前だから絶対に危険」というわけではありません。


4. どういうときに NextAuth.js を選ぶとよいか

次のような場合は、NextAuth.js を検討する価値が高いです。

  • Google / GitHub などのソーシャルログイン を入れたい(パスワードを減らせる+実装の手間とバグを減らせる)。
  • セッション・CSRF・トークン回り を「自分で設計・検証し続ける」よりも、実績あるライブラリに任せたい
  • セキュリティアップデート を自前で追いかけるリソースを減らしたい。

逆に、

  • メール+パスワードのみ でよく、現状の実装に自信がある。
  • 既存の認証フロー(JWT・Cookie 名・クライアント連携)を大きく変えたくない。

といった場合は、無理に NextAuth に移行しなくても、現状の設計を維持しつつ運用で固める選択もありです。


5. まとめ

  • パスワード漏洩などのリスクについては、NextAuth.js を使ったからといって自動で安全になるわけではなく、今の bcrypt+平文保存なしの実装でも、同等レベルまで安全にできます。
  • 「実績あるライブラリで全体を固めたい」「OAuth を入れたい」「セッション・CSRF をライブラリに任せたい」 という意味では、NextAuth.js を使う方が安全・安心しやすいと言えます。

なので、

  • 「パスワード漏洩が心配」 → 現状の実装を維持しつつ、JWT_SECRET や HTTPS などの運用をしっかりするのでもリスクは抑えられます。
  • 「認証全体を実績ある形にしたい/OAuth を入れたい」 → NextAuth.js の導入を検討する、という整理がしっくりきます。

Discussion