はじめに
WebアプリケーションやAPIの開発において「認証」と「認可」は最も重要な仕組みのひとつです。
ログインや権限チェックがなければ、不正アクセスや情報漏洩に直結します。しかし、セッションIDやCookie、アクセストークンやJWTといった具体的な方式は複数あり、それぞれに長所と短所があります。
本記事では認証・認可の基本概念と、実際にシステムを設計するときにどの仕組みを選ぶべきかを整理します。
認証・認可とは
認証
結論
「あなたは誰か?」を確認する仕組み。
方法
- ID / パスワード認証
最も一般的。パスワードの強度や保存方法(ハッシュ化)が重要。 - 多要素認証 (MFA / 2FA)
パスワード+SMSコードやワンタイムパスワード、認証アプリ。 - 生体認証
指紋認証や顔認証など。
認可
結論
「あなたは何ができるか?」を制御する仕組み。
方法
- ロールベースアクセス制御 (RBAC: Role-Based Access Control)
管理者(Admin)、編集者(Editor)、閲覧者(Viewer)など。
権限の割当てを「役割」に集約することで運用が楽。 - 属性ベースアクセス制御 (ABAC: Attribute-Based Access Control)
ユーザー属性(所属部署、契約プラン、時間帯など)に基づいて柔軟に制御。 - ポリシーベース制御
JSONやYAMLで「誰が、どのリソースに、どんな操作をできるか」を定義。
「認証 = ログイン」「認可 = 権限チェック」と認識すると良さそう。
認証・認可を実施する仕組み
セッションIDとCookie
ユーザーがログインするとサーバー側で「セッションID」を発行し、ブラウザにはCookieに保存される。
以降のリクエストではブラウザが自動的にCookie: SESSIONID=xxxx
を送信するため、サーバーは「このIDは誰のセッションか?」を確認して処理する。
セッション情報はサーバー側に保存するので「ステートフル」な方式。
→ Webアプリ(RailsやSpring MVCなど)でよく使われる。
Bearerトークン
HTTPのAuthorizationヘッダー
でBearer <token>
という形で渡す方法。
「Bearer = 持っている人が正規ユーザーとみなす」という仕組み。
トークンの中身は単なるランダム文字列のこともあれば、JWTのこともある。
→ APIやSPAでよく利用される。
JWT (JSON Web Token)
最近よく使われるトークン形式の1種。ヘッダー・ペイロード・署名の3部構成で、ペイロードにはユーザーIDや有効期限を含められる。
サーバー側はDBを見なくても署名を検証するだけで「誰か」を判断できるため、ステートレスに動作できる。
ただしトークン自体は暗号化されていないので、中身は誰でも読める(改ざんはできない)。機密情報を直接入れないことが大切。
仕組みの選択・使い分け
選定観点(要点)
フロントの形態
SSR中心(Rails, Django, Spring MVC, Next.js SSRなど)のWebアプリは、HTTPリクエスト・レスポンスのライフサイクル*がCookieと相性が良い。
→ Set-CookieでセッションIDを配布すれば、以後はブラウザが自動で送ってくれる。
※HTTPリクエスト・レスポンスのライフサイクルとは
リクエストごとにサーバーが処理してHTMLを生成し、レスポンスとして返す一往復の流れ
SPA(React/Vue/AngularのCSR)、モバイルアプリ、外部システム連携では、API呼び出しを自前で制御するため、HTTPヘッダにトークンを載せる方がやりやすい。
スケーラビリティ
Cookieベースのセッション方式では、セッション情報をサーバーが保持するため、複数サーバー環境で使用する場合は、どのサーバーにリクエストが届いても同じ状態を扱えるように、Sticky Sessionでサーバーを固定したり、RedisやMemcachedでセッションを共有する必要がある。
そのため、サーバーを横に増やすほど構成が複雑になりがち。
一方でBearerトークン(JWTなど)の場合、認証情報がトークン自体に含まれているためサーバー側は状態を持たず、どのサーバーにリクエストが届いても検証が可能。
このため、ステートレスで水平スケールしやすいという利点がある。
失効・強制ログアウト
Cookieベースのセッション方式では、サーバー側でセッションを削除することで即時にログアウトを実現できる。
対してBearerトークンは有効期限を持たせるのが基本で、期限切れを待たなければならず、強制的に無効化する場合はブラックリストの管理など追加の仕組みが必要になる。
そのため、即時失効という観点では、Cookieベースの方が有利であり、Bearerは設計上の工夫が求められる。
CSRFとXSSへの耐性
Cookieは、ブラウザが自動的に送信する仕組みのため、外部サイトからの不正リクエストを利用するCSRF攻撃に弱く、その対策としてSameSite属性やCSRFトークンの導入が不可欠。
対してBearerトークンは、JavaScriptで明示的にHTTPヘッダへ設定するためCSRF攻撃の影響は基本的に受けないが、逆にJavaScriptから参照できることによってXSS攻撃で盗まれるリスクが高まる。
そのため、CookieはCSRF対策が必須、BearerはXSS対策を特に強化する必要がある。
(認証・認可設計時のセキュリティ脆弱性まとめ)[https://qiita.com/saburo555/items/024a99e2fb0b608a7454]
「セッションID+Cookie方式」か「アクセストークン(Bearer)方式」かは、フロントの形態・スケーラビリティ・セキュリティ要件などで決めると良さそう!
まとめ
セッションID+Cookie方式とアクセストークン方式は一長一短で、セッションは即時失効や管理がしやすい一方、スケールやCSRF対策に注意が必要。
逆にアクセストークンはステートレスでAPIと相性が良い反面、XSSによる盗難リスクや強制無効化の難しさが課題。
結局「どちらが正解か」ではなく、システムの特性や要件に応じて適切に選び、弱点を補う仕組みをセットで考えることが大事だと学びました。