私がこれまで書いてきたすべてのプロジェクト計画には、必ず「認証 — 2日」という項目がありました。
そして、すべてのプロジェクト振り返りには、「認証に2週間かかった」というメモがあります。
私はこれまで4回、認証システムを構築してきました。毎回、見積もりを甘く見ています。その理由と、最終的に学んだことをお伝えします。
氷山の一角
あなたが思う認証とは:
- ログインフォーム
- トークンを保存する
- トークンが有効か確認する
- 完了
実際の認証とは:
- ログインフォーム(メール/パスワード + OAuth + マジックリンク + MFA?)
- パスワードのハッシュ化(bcrypt、argon2、コスト係数は?)
- セッション管理(JWT vs セッションクッキー vs 両方?)
- トークンリフレッシュ(サイレントリフレッシュ、ローテーション、失効)
- CSRF対策(Same-Siteクッキー、ダブルサブミットトークン)
- レート制限(ログイン、登録、パスワードリセット時)
- パスワードリセットフロー(トークン生成、有効期限、使い捨て)
- メール確認(トークン、再送信ロジック、メール変更時の処理)
- アカウントロックアウト(試行回数は?ロック解除フローは?)
- ロールベースのアクセス制御(管理者 vs ユーザー vs モデレーター)
- APIキー管理(プログラムによるアクセス用)
- パスワード変更時のセッション無効化
- 「ログイン状態を保持する」 vs 「このセッションのみ」
- 新しいデバイスからのログイン通知
- 監査ログ(誰が、いつ、どこからログインしたか)
これで15以上の機能になります。それぞれ1〜2日かかるとすれば、1ヶ月は見ておく必要があります。
今の私のやり方:Supabase Authを使って拡張する
カスタム認証を2回構築して、どちらも苦労した経験から、今はSupabase Auth(またはClerk、Auth.js)から始めるようにしています。これらが対応してくれるのは:
- bcryptによるメール/パスワード認証
- OAuthプロバイダー(Google、GitHub、Discord)
- リフレッシュ機能付きJWTトークン
- メール確認
- パスワードリセット
- セッション管理
- レート制限
これで認証の80%はカバーでき、認証にフルタイムで取り組んでいる人たちが処理してくれます。私は、自分のアプリに固有の残り20%に集中します:
\\
