Webアプリの認証機能を実装する

パスワード認証を題材に、登録、ログイン、セッション、ログアウト、パスワード再設定を安全につなぐ実装手順。

作成日: 2026-07-31 / 更新日: 2026-07-31

キーワード: authentication implementation / login / password hash / session / password reset / rate limit

概要

認証機能は、ログイン画面だけでは完結しません。

アカウント登録、パスワード保存、ログイン試行の制御、セッション発行、ログアウト、パスワード再設定までを一つの流れとして設計する必要があります。認証後の操作では、利用者がその処理を実行してよいかを確認する認可も必要です。

このページでは、ブラウザから利用するWebアプリにパスワード認証を実装する場合を中心に、処理のつながりと確認点を整理します。特定のフレームワークには依存しません。

実装前に決めること

コードを書く前に、少なくとも次の項目を決めます。

社内システムでは、既存のID基盤やSSOを利用できる場合があります。認証を一から作る前に、組織の標準方式やフレームワークの認証機能を確認します。

全体の構成

パスワード認証とサーバー側セッションを使う場合、構成は次のようになります。

ブラウザ
  ├─ 登録・ログイン要求 ──> 認証処理 ──> ユーザー情報
  └─ Session ID Cookie ──> セッション検証 ──> セッション情報

ブラウザには推測されにくいSession IDだけをCookieで持たせ、ログイン中のユーザーIDや有効期限はサーバー側で管理します。

最小限のデータ設計

users

項目内容
id内部で使うユーザー識別子
login_idログインに使う値。重複を禁止する
password_hashパスワード用アルゴリズムで生成したハッシュ
status有効、停止、退会などの状態
email_verified_atメール確認が必要な場合の確認日時

ログインIDは入力時と検索時に同じ規則で正規化します。重複はアプリケーションの確認だけに頼らず、データベースの一意制約でも防ぎます。

sessions

項目内容
idセッションを識別する値
user_idログイン中のユーザー
created_at発行日時
expires_at絶対的な有効期限
last_seen_at無操作期限を管理する場合の最終利用日時
revoked_atログアウトなどで無効化した日時

password_reset_tokens

項目内容
token_hash再設定用トークンのハッシュ
user_id対象ユーザー
expires_at有効期限
used_at使用済み日時

再設定用トークンは十分にランダムな値を生成し、短い有効期限を設定します。データベースには、可能であればトークンそのものではなくハッシュを保存します。

アカウント登録

登録処理の基本的な流れは次のとおりです。

  1. ログインIDとパスワードを受け取る
  2. ログインIDを正規化し、形式と重複を確認する
  3. パスワードポリシーを確認する
  4. パスワード用のアルゴリズムでハッシュ化する
  5. ユーザーを保存する
  6. 必要であれば、メールアドレス確認用のトークンを発行する

パスワードは平文でも、復号できる暗号文でも保存しません。Argon2id、scrypt、bcrypt、PBKDF2など、利用する環境で推奨されるパスワード保存用の実装を使います。saltの生成や比較処理も、十分に利用されているライブラリやフレームワークに任せます。

パスワードの規則は、文字種を増やすことだけに寄せず、十分な長さ、よく使われるパスワードの拒否、試行回数の制御と組み合わせます。入力されたパスワードを黙って途中で切り捨ててはいけません。

ログイン

ログイン処理は、次の順序で考えます。

  1. HTTPSでログインIDとパスワードを受け取る
  2. ログインIDを登録時と同じ規則で正規化する
  3. 対象ユーザーを検索する
  4. 保存済みハッシュと入力されたパスワードを検証する
  5. アカウント状態を確認する
  6. 新しいセッションを発行する
  7. Session IDをCookieに設定する

ユーザーが存在しない場合とパスワードが違う場合で、「そのメールアドレスは登録されていません」のように応答を分けると、アカウントの存在を推測されます。画面には「ログインIDまたはパスワードが正しくありません」のような共通メッセージを返します。

ユーザーが存在しない場合だけ処理時間が極端に短くならないよう、ダミーのパスワードハッシュを検証する方法もあります。画面上の文言だけでなく、応答時間から情報が漏れないかも確認します。

ログイン試行を制限する

ログイン回数を無制限にすると、総当たり攻撃や、漏えいしたパスワードを別サービスで試す攻撃を受けやすくなります。

送信元IPだけで制限すると、共有回線の利用者をまとめて止めたり、攻撃者にIPを切り替えられたりします。反対にアカウントだけで制限すると、第三者が意図的に対象アカウントをロックできます。複数の情報を組み合わせて段階的に制限します。

セッションを発行する

認証成功後は、ログイン前のSession IDをそのまま使わず、新しいSession IDを発行します。これにより、攻撃者が事前に用意したセッションを利用者に使わせるセッション固定攻撃を防ぎます。

Cookieの設定例は次のとおりです。

Set-Cookie: __Host-session=<推測困難な値>; Path=/; Secure; HttpOnly; SameSite=Lax

SameSite=LaxStrictかは、外部サイトから戻る導線やSSOの有無も含めて決めます。SameSite属性だけに任せず、状態を変更するリクエストではCSRFトークンも検証します。

Session IDをURL、HTML、アクセスログに含めません。セッションには無操作時の期限と絶対的な期限を設け、期限切れや無効化済みのセッションは拒否します。

認証後は毎回認可する

認証できたことは、すべての処理を実行してよいことを意味しません。

各リクエストでは、Session IDからユーザーを特定した後、そのユーザーが対象データを閲覧・更新できるかをサーバー側で確認します。ボタンを非表示にするだけでは認可になりません。URLやリクエストを直接送られても拒否できる必要があります。

ログアウト

ログアウトでは、画面をログインページへ移動するだけでは不十分です。

  1. サーバー側のセッションを無効化する
  2. ブラウザのSession Cookieを期限切れにする
  3. ログアウト後のSession IDでアクセスできないことを確認する

必要に応じて「この端末だけ」と「すべての端末」のログアウトを分けます。ログアウトを状態変更として扱い、POSTとCSRF対策を使う設計も検討します。

パスワード再設定

パスワード再設定は、ログインとは別の認証経路になります。ここが弱いと、強いパスワードを設定しても回避されます。

  1. ログインIDまたはメールアドレスを受け取る
  2. アカウントの有無にかかわらず同じ応答を返す
  3. 対象が存在する場合だけ、十分にランダムな一回限りのトークンを発行する
  4. HTTPSの再設定URLを本人が確認できる経路へ送る
  5. 有効期限、未使用、対象ユーザーを検証する
  6. 新しいパスワードを保存し、トークンを使用済みにする
  7. 完了通知を送り、既存セッションを失効させるか方針に従って処理する

秘密の質問だけを本人確認に使う方法は、答えを推測・調査されやすいため避けます。再設定トークンをログへ出したり、使用後も再利用できる状態にしたりしてはいけません。

セッションとJWTの選び方

ブラウザ中心の一般的なWebアプリでは、まずサーバー側セッションを検討します。サーバーで状態を無効化でき、ログアウトや権限変更を反映しやすいためです。

JWTは、複数サービス間で検証するAPIなどで役立つことがあります。ただし、JWTに変えただけで認証が安全になるわけではありません。保存場所、漏えい時の失効、短い有効期限、鍵の管理を別途設計する必要があります。要件がない段階で、ログイン機能だからJWTを選ぶ必要はありません。

ログに残すもの、残さないもの

認証の成功・失敗、アカウント停止、再設定要求、セッション失効などは、調査できる形で記録します。ただし、次の値はログへ残しません。

利用者を追跡するための内部IDやリクエストIDを使い、秘密情報を含めずに処理をたどれるようにします。

テスト観点

観点確認内容
正常ログイン正しい情報で新しいセッションが発行される
認証失敗未登録IDと誤ったパスワードで同じメッセージになる
試行制限短時間の連続失敗が制限され、正常利用へ戻せる
セッション固定ログイン前後でSession IDが変わる
CookieSecureHttpOnlySameSitePathが意図どおりである
有効期限無操作期限と絶対期限の後にアクセスできない
ログアウト無効化したSession IDを再利用できない
CSRF状態変更時に不正なトークンを拒否する
再設定期限切れ、使用済み、改ざんされたトークンを拒否する
認可他人のIDを指定してもデータを閲覧・更新できない
ログパスワードやトークンが記録されない

実装の順序

最初からすべてを作るのではなく、次の順序で小さく確認すると処理を追いやすくなります。

  1. ユーザーデータとパスワードハッシュ
  2. ログインと共通エラーメッセージ
  3. セッション発行とCookie属性
  4. 認証必須ページと認可チェック
  5. ログアウトとセッション失効
  6. ログイン試行の制限と監視
  7. パスワード再設定
  8. 必要に応じてメール確認、MFA、SSO

避けたい実装

参考資料

更新履歴

  • 初版作成

関連項目

このページを参照しているページ