Webアプリケーション開発において、認証方式の選択は システムのスケーラビリティ、セキュリティ、保守性に大きな影響を与える設計判断である。この記事では、セッションベース認証とトークンベース認証について、技術的な詳細から実装上の考慮事項まで包括的に比較・解説する。
認証(Authentication)とは、システムにアクセスしようとするユーザーが「本人である」ことを確認するプロセスである。ユーザーの身元を検証し、正当なユーザーのみがシステムにアクセスできるようにする仕組みである。
認証 vs 認可の違い:
認証システムが提供する基本的な機能には以下のものがある。
身元確認
セッション管理
セキュリティ制御
監査・ログ
認証システムに求められる非機能要件には以下のものがある。
パフォーマンス
スケーラビリティ
可用性
セキュリティ
保守性
システムの根幹となる機能であるため、高い可用性やスケーラビリティが求められる。
セッションベース認証は、サーバー側でユーザーのログイン状態を管理する方式である。
graph TB
subgraph "クライアント側"
Browser[ブラウザ]
end
subgraph "サーバー側"
LB[ロードバランサ]
App1[アプリサーバー1]
App2[アプリサーバー2]
App3[アプリサーバー3]
Session[(セッションストア<br/>Redis/Database)]
DB[(ユーザーDB)]
end
Browser -->|Cookie: sessionid| LB
LB --> App1
LB --> App2
LB --> App3
App1 <-->|セッション読み書き| Session
App2 <-->|セッション読み書き| Session
App3 <-->|セッション読み書き| Session
App1 <-->|ユーザー情報取得| DB
App2 <-->|ユーザー情報取得| DB
App3 <-->|ユーザー情報取得| DB
主なコンポーネントには以下のものがある。
sequenceDiagram
participant U as ユーザー
participant B as ブラウザ
participant S as サーバー
participant SS as セッションストア
participant DB as ユーザーDB
U->>B: ログイン情報入力
B->>S: POST /login (ID, Password)
S->>DB: ユーザー認証
DB-->>S: 認証結果
alt 認証成功
S->>S: セッションID生成
S->>SS: セッション情報保存
SS-->>S: 保存完了
S-->>B: Set-Cookie: sessionid=xxx
B-->>U: ログイン成功
else 認証失敗
S-->>B: 401 Unauthorized
B-->>U: ログイン失敗
end
sequenceDiagram
participant B as ブラウザ
participant S as サーバー
participant SS as セッションストア
participant DB as アプリDB
B->>S: GET /api/data (Cookie: sessionid=xxx)
S->>SS: セッション確認
SS-->>S: セッション情報
alt セッション有効
S->>DB: データ取得
DB-->>S: データ
S-->>B: 200 OK + データ
else セッション無効/期限切れ
S-->>B: 401 Unauthorized
end
sequenceDiagram
participant B as ブラウザ
participant S as サーバー
participant SS as セッションストア
B->>S: POST /logout (Cookie: sessionid=xxx)
S->>SS: セッション削除
SS-->>S: 削除完了
S-->>B: Set-Cookie: sessionid=削除
B-->>B: Cookie削除
セキュリティ
シンプルな実装
細かい制御
ブラウザ対応
スケーラビリティの制約
パフォーマンスの課題
運用の複雑性
マルチプラットフォーム対応
障害時の影響
トークンベース認証は、クライアント側でトークンを保持し、各リクエストでトークンを送信して認証する方式である。
graph TB
subgraph "クライアント側"
Browser[ブラウザ]
Token[JWTトークン<br/>ローカルストレージ]
end
subgraph "サーバー側"
LB[ロードバランサ]
App1[アプリサーバー1]
App2[アプリサーバー2]
App3[アプリサーバー3]
Auth[認証サーバー]
DB[(ユーザーDB)]
end
Browser <-->|トークン保存・取得| Token
Browser -->|Authorization: Bearer token| LB
LB --> App1
LB --> App2
LB --> App3
App1 -->|トークン検証| App1
App2 -->|トークン検証| App2
App3 -->|トークン検証| App3
Browser -.->|初回認証時のみ| Auth
Auth -.->|JWT発行| Browser
Auth <-->|ユーザー情報取得| DB
主なコンポーネントには以下のものがある。
sequenceDiagram
participant U as ユーザー
participant B as ブラウザ
participant Auth as 認証サーバー
participant DB as ユーザーDB
U->>B: ログイン情報入力
B->>Auth: POST /auth/login (ID, Password)
Auth->>DB: ユーザー認証
DB-->>Auth: 認証結果
alt 認証成功
Auth->>Auth: JWTトークン生成
Auth-->>B: 200 OK + JWT Token
B->>B: トークンをローカルストレージに保存
B-->>U: ログイン成功
else 認証失敗
Auth-->>B: 401 Unauthorized
B-->>U: ログイン失敗
end
sequenceDiagram
participant B as ブラウザ
participant S as サーバー
participant DB as アプリDB
B->>B: ローカルストレージからトークン取得
B->>S: GET /api/data (Authorization: Bearer token)
S->>S: トークン検証(署名・有効期限・発行者)
alt トークン有効
S->>DB: データ取得
DB-->>S: データ
S-->>B: 200 OK + データ
else トークン無効/期限切れ
S-->>B: 401 Unauthorized
end
sequenceDiagram
participant B as ブラウザ
participant Auth as 認証サーバー
B->>B: ローカルストレージからトークン削除
B->>Auth: POST /auth/logout
Auth->>Auth: ログアウト記録(監査用)
Auth-->>B: 200 OK
注意: JWTトークンは自己完結型のため、サーバー側での即座な無効化は困難である。実際の無効化は以下の方法で実現される:
スケーラビリティ
パフォーマンス
マルチプラットフォーム対応
ステートレス
標準化
セキュリティリスク
トークンサイズ
実装の複雑性
デバッグの困難性
ブラウザ制限
項目 | セッションベース | トークンベース |
---|---|---|
状態管理 | ステートフル(サーバー側で状態保持) | ステートレス(トークンに情報を含む) |
データ保存場所 | サーバー側(セッションストア) | クライアント側(ローカルストレージ等) |
ネットワーク通信 | 毎リクエストでセッション確認 | トークン検証のみ(ローカル処理) |
スケーラビリティ | セッションストア依存 | 水平スケーリング容易 |
セキュリティモデル | サーバー側制御中心 | クライアント・サーバー分散型 |
指標 | セッションベース | トークンベース |
---|---|---|
認証処理時間 | セッションストアアクセス時間に依存 | トークン検証時間(通常数ms) |
ネットワーク負荷 | セッションID(小) | JWT(中〜大) |
サーバー負荷 | セッションストアへの読み書き | CPU集約的な署名検証 |
メモリ使用量 | セッション数に比例 | ほぼ一定 |
脅威 | セッションベース | トークンベース |
---|---|---|
セッション固定攻撃 | 脆弱(対策必要) | 影響なし |
セッションハイジャック | 脆弱(HTTPS必須) | 脆弱(HTTPS必須) |
XSS攻撃 | HttpOnly Cookie で軽減 | ローカルストレージ使用時は脆弱 |
CSRF攻撃 | 脆弱(CSRF Token必要) | 影響軽微 |
トークン漏洩 | セッションID漏洩時は限定的 | JWT漏洩時は影響大 |
従来型のWebアプリケーション
高いセキュリティが求められる場合
シンプルな構成を望む場合
モダンなWebアプリケーション
スケーラビリティが重要な場合
マルチプラットフォーム対応
セッションストアの選択
セキュリティ対策
運用面の配慮
トークン設計
セキュリティ対策
運用面の配慮
セッションベース認証とトークンベース認証は、それぞれ異なる特徴と適用場面を持つ認証方式である。
適切な認証方式の選択は、システムの要件、スケール、セキュリティ要求、開発チームのスキル、運用体制などを総合的に考慮して決定する必要がある。また、両方式を組み合わせたハイブリッドなアプローチを取ることも可能である。
技術の進歩とともに認証方式も進化し続けているため、継続的な技術動向の把握と、システムの成長に合わせた認証方式の見直しも重要な要素となる。