Web開発ではさまざまな認証方式がでてきますが、まとめておかないとそれぞれの方式のイメージやメリデメなどがわからないため、自分のわかっている範囲でまとめをしておこうと思います。
セッション・クッキー方式
サーバーがセッションIDを発行し、クライアントのCookieに保存する従来型の認証方式。
サーバー側でセッション情報を管理するステートフルな仕組みで、実装がシンプルで多くのWebフレームワークに標準搭載されています。ブラウザベースのWebアプリケーションでよく使われています。
※セッションの情報自体はDB以外にもメモリキャッシュなどいろいろ考えられます。
メリット:
-
実装の容易さ
- 多くのWebフレームワークで標準的にサポート
- 従来からの確立された認証方式で実装例が豊富
- セッション管理をサーバー側で一元的に行える
-
セキュリティ面
- セッションIDのみをクライアントに保持し、機密情報はサーバーで管理
- セッションタイムアウトの設定が容易
- セッション無効化(ログアウト)が確実に行える
デメリット:
-
スケーラビリティの課題
- サーバーでセッション情報を保持するため、メモリ消費が増大
- 複数サーバーでの運用時、セッション情報の同期が必要
- 水平スケーリングが複雑になる
- RestfulAPIとの親和性の低さ
-
ステートフル性による制約
- サーバー側で状態を保持する必要がある
- サーバーダウン時にセッション情報が失われる可能性
-
API利用での制約
- Cookieベースの制限
- クロスオリジンでの制約
トークン(Opaque Token)方式
ランダムな文字列をトークンとして発行し、サーバーのデータベースでトークンとユーザー情報を紐付けて管理する方式です。
トークン自体には意味がなく、検証には必ずデータベースへの問い合わせが必要となります。即座に無効化できるためセキュリティ性が高く、Refresh Tokenとしてよく使われています。
メリット:
-
APIとの親和性
- クロスプラットフォームでの実装が容易
- モバイルアプリなどでも扱いやすい
-
セキュリティ管理
- トークンの即時無効化が可能
- トークンの有効期限管理が容易
- アクティブなセッション(トークン)の把握が容易
-
実装の柔軟性
- トークンに紐づく情報の管理が自由
デメリット:
-
パフォーマンス
- 毎リクエストでDBアクセスが必要
- トークン検証のオーバーヘッド
- DBへの負荷が高い
-
スケーラビリティ
- トークン情報のDB同期が必要
使い分けのポイント:
-
アプリケーションの性質
- Webアプリケーション中心 → セッション認証
- API中心のシステム → トークン認証
-
スケール要件
- 単一サーバー/小規模 → セッション認証
- 大規模/分散システム → トークン認証
-
クライアントの多様性
- ブラウザのみ → セッション認証
- 多様なクライアント → トークン認証
JWT
ユーザー情報をJSON形式でエンコードし、デジタル署名を付与した自己完結型のトークン。
サーバーはデータベース不要で署名検証のみで認証できるステートレスな仕組み。マイクロサービスやAPI認証に最適ですが、有効期限まで無効化できない課題があります。
JWTとは?
JWTは「JSON Web Token」の略です。これは「デジタル署名付きのIDカード」のようなもの
仕組みを例え話で説明すると...
お店(ウェブサイト)に行く時のことを想像してください:
- ログイン(身分証明)
あなた:「こんにちは!私はAさんです。パスワードは1234です」
お店:「確認しました。このIDカード(JWT)を渡します」
- IDカード(JWT)の中身
- 名前:Aさん
- 会員番号:12345
- 有効期限:2024年3月1日まで
- お店の印鑑(デジタル署名)
- お店を利用する時(APIにアクセスする時)
あなた:「商品を見たいです。はい、IDカードです」
お店:「IDカードを確認しました。どうぞご覧ください」
メリット
-
完全なステートレス
- サーバー側でセッション情報を保持する必要がない
- データベースへのクエリが不要
- サーバーのメモリを消費しない
-
セキュリティ管理
- どのサーバーでも独立してトークン検証可能
-
クロスドメイン、クロスオリジリン対応
- CORSに強い
- 複数のサブドメイン・サービス間で共有可能
- マイクロサービスアーキテクチャに最適
- モバイルに最適
-
改ざん検知が可能
- デジタル署名により改ざんを検出
- HMAC、RSA、ECDSAなど複数のアルゴリズム対応
- 信頼性の高い検証メカニズム
デメリット:
- トークンの無効化が困難
- 有効期限まで強制的に無効化できない
- ログアウトしてもトークンは有効なまま
- トークンサイズの肥大化
- 200文字〜1000文字
Opaque tokenとの違い
-
トークン生成と検証
- JWT: トークン自体に情報が含まれ、秘密鍵で検証可能
- Opequeトークン: ランダムな文字列で、必ずDBで検証が必要
-
サーバーサイドの状態管理
- JWT: 基本的にステートレス(DB検証不要)
- Opaqueトークン: トークンとユーザー情報をDBで管理
-
トークンの無効化
- JWT: 有効期限までサーバーで無効化が難しい
- Opaqueトークン: DBから削除することで即時無効化可能
-
セキュリティ特性
- JWT: 改ざん検知が可能
- Opaqueトークン: 予測不可能な文字列であることが重要
Oauth
外部サービス(Google、GitHubなど)のアカウントを使って認証・認可を行うオープンな標準プロトコルです。
ユーザーはパスワードを共有せず、限定的な権限のみをアプリケーションに委譲できます。
ソーシャルログインやAPI連携に広く使われています。
OAuthのメリット:
-
セキュリティ
- パスワードを直接アプリケーションに渡す必要がない
- 既存のアカウント(Google、Facebookなど)でログイン可能
- 複数サービスで同じアカウントが使える(シングルサインオン)
- パスワードを覚える必要が少ない
-
開発・運用
- 認証基盤の実装・運用コストを削減できる
- 標準化されたプロトコルで相互運用性が高い
- セキュリティのベストプラクティスが組み込まれている
OAuthのデメリット:
-
複雑性
- 実装が比較的複雑
- フローの理解・管理が必要
-
依存性
- 認証プロバイダーに依存
- プロバイダーの障害時にサービスに影響
- プロバイダーの仕様変更への対応が必要
まとめ
それぞれの認証方式を比較した表を作成します。
| 認証方式 | 特徴 | メリット | デメリット | 適した用途 |
|---|---|---|---|---|
| セッション・クッキー | ・サーバーサイドでセッション情報を保持 ・クライアントにはセッションIDをクッキーとして保存 ・ステートフル(状態を持つ)な認証方式 |
・実装が比較的シンプル ・セッションの無効化が容易 ・多くのフレームワークで標準サポート ・ブラウザの標準機能を利用 |
・サーバーリソースを消費 ・スケーリングが複雑 ・CSRF攻撃への対策が必要 ・モバイルアプリとの相性が悪い |
・Webアプリケーション中心のシステム ・シンプルな要件の場合 |
| トークン | ・サーバーがアクセストークンを発行 ・クライアントがトークンを保持 ・ステートレスな認証が可能 |
・スケーラビリティが高い ・クロスドメイン対応が容易 ・モバイルアプリとの相性が良い ・サーバー負荷が低い |
・トークンの管理が必要 ・漏洩時のリスクが高い ・通信オーバーヘッド ・有効期限管理が必要 |
・モバイルアプリケーション ・分散システム |
| JWT | ・JSON形式の情報をエンコード ・署名付きのトークン ・クレームを含められる |
・完全にステートレス ・トークンに情報を含められる ・改ざん検知が可能 ・標準化されている |
・トークンサイズが大きい ・無効化が難しい ・秘密鍵の管理が重要 ・情報漏洩リスク |
・マイクロサービス ・分散システム ・サービス間認証 |
| OAuth | ・認可プロトコル ・サードパーティ認証 ・アクセス権限の委譲が可能 |
・標準化された安全なフロー ・細かい権限制御が可能 ・パスワードを直接扱わない ・シングルサインオン対応 |
・実装が複雑 ・外部サービスへの依存 ・フロー理解が必要 ・プロバイダーの障害影響 |
・外部サービス連携 ・ソーシャルログイン |