1-1. 認証と認可の基本 - AuthN と AuthZ を混同しない
所要時間: 30-45分 ゴール: 認証(AuthN)と認可(AuthZ)の違いを明確に説明できる。主要な認証方式・認可方式の用途とトレードオフを理解する コミット内容: 自分のサービス(架空でOK)の認証/認可方針メモを
~/learn/security/day01_auth_design.mdに残す
前章とのつながり
このレッスンの位置づけ
セキュリティ章の 最初の扉。以降のすべて(パスワード保存、HTTPS、JWT、CSRF、認可設計)は「誰がアクセスし、何を許すか」という本章の枠組みの上に積み上がる。
- 次章 1-2 パスワードハッシュ: 認証の「知識要素」を どう保存するか に踏み込む
- Level 2 2-1 JWT / 2-2 セッション管理: 認証結果を どう運ぶか
- Level 2 2-6 認可設計: 認可を どう実装するか の深掘り
ここで AuthN と AuthZ の境界が曖昧なまま進むと、後続のレッスンが全部ぼやけて入ってくる。最初の1時間で土台を固めるのがコスパ最高。
実害シーン: 認証/認可の事故は「億単位」で起きる
- First American Financial (2019): URL の番号を
?docId=123から?docId=124に書き換えるだけで他人の住宅ローン書類が見える状態だった → 8.85億件流出。これは認可(AuthZ)の欠陥- Optus (2022): 認証なしの API エンドポイントを叩くだけで全顧客の個人情報取得可能 → 約1000万件流出、CEO 辞任
- メルカリ (2017): 一時 Cookie の取り扱いミスで他人のアカウントに「ログイン状態」で入れる事象 → 緊急サービス停止
これらはすべて 「ログインさせる仕組み」と「許可する仕組み」を分けて設計できていなかった ことが根本原因。本章はその境界線を引く回。
大前提: なぜここから始めるか
セキュリティの話題の9割は 「誰がアクセスしているか」「その人に何を許すか」 をめぐる議論です。にも関わらず、現場で一番混同されるのが「認証」と「認可」。
- 「ログインさせる」のは認証(Authentication / AuthN)
- 「ログインした人に管理画面を開かせる」のは認可(Authorization / AuthZ)
これがゴチャゴチャしたまま設計すると、
- 管理画面のURLを知っていれば一般ユーザーでも入れる(認可が抜けてる)
- パスワード認証は通すのに、強制ログアウトの仕組みがない(セッション設計が破綻)
- OAuthで「ログイン」と「権限委譲」を混ぜて誤実装
といった事故が起きる。OWASP Top 10 の A01(Broken Access Control)と A07(Authentication Failures)は毎年上位に居座っていて、これらは「AuthN と AuthZ を分けて設計できていない」が根本原因です。
このレッスンでは 架空の SaaS「TaskNote」(社内タスク管理ツール)にログイン機能を実装する という想定で、用語と方式を整理する。
セッション①: 認証と認可は何が違うか(25-30分)
0. 録画&メモ準備
mkdir -p ~/log ~/learn/security
script ~/log/security_day01.log1. 認証(Authentication / AuthN)とは何か
「あなたは誰ですか?」を確認するプロセス。本人確認。
ユーザー: 「私は alice です。パスワードは hunter2 です」
↓
サーバー: パスワードDBと照合
↓
サーバー: 「OK、確かに alice さんですね」
認証の本質
「自称している身元」が正しいかを確かめる。「本人かどうか」しか興味がない。
認証が成功すると、サーバーはそのリクエストに「これは alice だ」という識別子を結びつける。以降のリクエストでも alice として扱われる(セッション / トークン経由)。
認証は 必ずしも信頼できるとは限らない: 「自称 alice」がパスワードを知っていただけで、本物の alice が漏洩させた可能性もある。だから多要素(MFA)などで強化する。
認証の3要素(3 factors)
認証の根拠は伝統的に3つに分類される:
- 知識要素(Something you know): パスワード、PIN、秘密の質問
- 所持要素(Something you have): スマホ、ハードウェアトークン、ICカード
- 生体要素(Something you are): 指紋、顔、虹彩
多要素認証(MFA / 2FA): これらのうち 2つ以上の異なる要素 を組み合わせる。パスワード(知識)+SMS(所持)が古典的MFA。
「パスワード + 秘密の質問」は両方とも知識要素なので 多要素にならない。これがよくある誤解。
2. 認可(Authorization / AuthZ)とは何か
「この人に X をさせていいか?」を判断するプロセス。
alice として認証済みのリクエスト: 「ユーザー bob のメール一覧を見せて」
↓
サーバー: alice は bob のメールにアクセスできるか?
↓
サーバー: 「alice は管理者ではないので NG。403 を返す」
認可の本質
「身元が確認できた」あとに 「その人が何をできるか」 を決める。
認可は 必ず認証の後に行う: 誰だか分からないと「何を許すか」も決まらない。
逆に 認証を通したから何でも許す は重大な事故。多くのサービスは「ログインさせたら勝ち」と勘違いしている。
認証成功 = 全権限OK、ではない
「ログインできた」と「管理画面が見られる」は別問題。ログインしたユーザーが偶然
/adminを叩いたら入れちゃった、というのが A01 Broken Access Control の典型パターン。認可チェックは 各エンドポイントごと に独立して行う必要がある。
3. 比較表で覚える
| 観点 | 認証 (AuthN) | 認可 (AuthZ) |
|---|---|---|
| 問い | あなたは誰? | 何をしていい? |
| 結果 | ユーザーID / セッション | 許可 / 拒否 |
| 失敗時HTTP | 401 Unauthorized | 403 Forbidden |
| タイミング | ログイン時、リクエスト到着時 | 各API呼び出し時 |
| 実装場所 | 認証ミドルウェア、SSO | 各ハンドラ、ポリシーエンジン |
| 例 | パスワード照合、JWT検証 | 「このユーザーは admin か?」 |
HTTPステータスの罠
仕様上は「401 = 認証失敗」「403 = 認可失敗」だが、現場では混同して使われている。
- 401: そもそも認証情報が無い / 無効(再ログインさせるべき)
- 403: 認証はできてるが、このリソースを見る権限が無い
「ログインしてください」を 403 で返している API は気持ち悪い。コードレビューで指摘ポイント。
4. 「TaskNote」での具体例
架空サービス TaskNote では:
| 機能 | 認証 | 認可 |
|---|---|---|
| ログインページ表示 | 不要 | 不要 |
| ログイン処理 | する(パスワード照合) | 不要 |
| 自分のタスク一覧 | 必須 | ログイン済みなら全員OK |
| 他人のタスク一覧 | 必須 | チーム内のみOK |
| 管理画面(全社のタスク) | 必須 | 管理者ロールのみ |
| パスワード変更 | 必須 | 本人のみ(他人のは変えられない) |
設計のコツ
エンドポイント設計の段階で 「この URL は誰がアクセスできる?」を表にする。
この表が雑だと実装も雑になる。雑な実装 = 認可バグ = 個人情報漏えい。
セッション②: 認証方式と認可方式のカタログ(25-30分)
5. 主要な認証方式
パスワード認証
ユーザー: ID + パスワード送信
サーバー: ハッシュ化したパスワードとDB照合
パスワード認証の本質
一番古典的で、一番油断ならない方式。実装の99%は「パスワードをどう保存するか」「どう照合するか」 にかかっている。
ハッシュ化、salt、bcrypt/argon2 などの詳細は次レッスン 1-2 パスワードハッシュ で扱う。
ユースケース: ほぼすべてのWebサービスの基本認証 落とし穴: 平文保存(論外)、SHA-256そのまま保存(弱い)、レート制限なし(ブルートフォース食らう)
SSO(Single Sign-On)
ユーザー: Google でログイン
↓
TaskNote: Google に「この人を認証してください」と委譲
↓
Google: 認証してトークンを返す
↓
TaskNote: トークンを検証して「この人は alice@example.com です」と信頼
SSO(シングルサインオン)の本質
認証を 外部のID Provider(IdP)に委譲する 仕組み。Google / Microsoft / Okta などが IdP として認証を代行してくれる。
ユーザー側: パスワードを覚える数が減る、サービスごとに作らなくていい サービス側: パスワード保存・リセットなどの 責任を負わなくて済む
裏で動くプロトコル
- OAuth 2.0: 認可フレームワーク(本来は「権限委譲」のための仕様)
- OpenID Connect (OIDC): OAuth 2.0 の上に認証機能を載せたもの。「Googleでログイン」は実態として OIDC
- SAML: エンタープライズ向け(古い)。Okta、社内システムでまだよく見る
ユースケース: 社内ツールで Google Workspace アカウントを使い回す、コンシューマ向けで「Twitterでログイン」を提供する 落とし穴: SSO に頼り切るとIdP障害で全社業務が止まる(Okta障害で社内ツール全滅、は2022年頃ニュースになった)
MFA(多要素認証 / Multi-Factor Authentication)
ステップ1: パスワード入力 → 通る
ステップ2: スマホアプリ(Google Authenticator など)の6桁コード入力 → 通る
↓ 両方OKで認証成功
MFA の本質
「パスワードを知っている」だけでは入れず、もう一つの要素(スマホを持っている、生体)を要求する。パスワード漏洩しても突破されにくくなる。
方式
- TOTP(Time-based One-Time Password): Google Authenticator、Authy など。30秒ごとに変わる6桁
- SMS OTP: 携帯にSMSで送る。今は非推奨(SIMスワップ攻撃で乗っ取られる)
- WebAuthn / Passkey: 公開鍵暗号ベース、フィッシング耐性が高い。次世代の本命
- ハードウェアキー: YubiKey などUSBデバイス
ユースケース: 管理者アカウント、金融サービス、社内SSO(社内ツールは全部MFA必須にすべき) 落とし穴: MFA 必須にしたら、リカバリーフロー(端末紛失時の救済)も設計しないと地獄。バックアップコード発行 + ヘルプデスク対応の体制必要
Passkey は今後の主流
2024年以降、Apple / Google / Microsoft が本格推進。パスワード不要 + 生体認証 + フィッシング耐性 の三拍子。
新規サービスを設計するなら最初から WebAuthn / Passkey を視野に入れる。
生体認証
生体認証は「ローカル」が原則
Face ID / Touch ID は 端末内 で照合される。生体データがサーバーに送られることは無い(少なくともAppleの仕組みでは)。
サーバーから見ると「端末で生体認証が通った」というシグナルが届くだけ。実態は WebAuthn / Passkey の MFA要素として組み込まれることが多い。
落とし穴: 「生体は最強」ではない。指紋は変更できないので、漏洩したら一生使えなくなる。サーバーに生体データそのものを送る設計は絶対にしない。
トークン認証(API Key、JWT)
トークン認証の本質
ログイン直後にサーバーが発行する「身分証」みたいな文字列。それを以降のリクエストで毎回提示する。
2つの代表的形式
- 不透明トークン(opaque token): ランダム文字列。サーバー側DBで「このトークン → alice」と紐付け管理
- JWT(JSON Web Token): 中身に情報を持ったトークン。署名付きで改ざん検知できる
Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiJhbGljZSJ9.xxxユースケース: モバイルアプリ、SPA(フロントエンドからAPI叩く構成)、サービス間通信 落とし穴: JWT は トークン無効化が難しい(漏洩しても期限切れまで使えてしまう)。Cookie の HttpOnly + SameSite で守るほうが安全なケースも多い。詳細は後の章で
6. 認可方式の代表選手
ロールベース(RBAC: Role-Based Access Control)
ユーザー alice → ロール「admin」
ユーザー bob → ロール「member」
「admin はすべて操作できる」
「member は自分のタスクのみ操作できる」
RBAC の本質
「役割(ロール)」に権限をまとめ、ユーザーにロールを付与する。
ユーザーごとに細かい権限を設定するのではなく、「admin」「editor」「viewer」のような役割を定義して使い回す。90%のサービスはこれで十分。
ユースケース: SaaS の管理者/一般ユーザー区分、社内ツールの部署別アクセス 落とし穴: ロールが増えすぎる「ロール爆発」。「営業部の中で関東チームだけ閲覧可」みたいな細かい条件をロールで表現しようとすると地獄
属性ベース(ABAC: Attribute-Based Access Control)
ルール: 「ユーザーの部署 == リソースの所有部署」ならアクセス可
ルール: 「現在時刻 ∈ 09:00-18:00」かつ「アクセス元IP ∈ 社内」ならアクセス可
ABAC の本質
ユーザー属性 + リソース属性 + コンテキスト を条件式で評価する。RBAC より柔軟だが複雑。
AWS IAM ポリシーは ABAC に近い。「タグ
team=blueがついたインスタンスのみ操作可」のような書き方ができる。ユースケース: 大企業の細かい権限制御、コンプライアンス要件が厳しい業界(金融・医療) 落とし穴: ポリシーが複雑になりすぎてレビュー不能になる。最初から ABAC を導入するのは過剰設計の典型
RBAC と ABAC の使い分け
- まず RBAC で始める
- ロールで表現しきれない条件が増えてきたら ABAC を部分的に導入する
- 詳細は Level 2-6 の認可深掘り回で扱う(予定)
7. 脅威モデル: 攻撃者は誰か、何を守るか
実装方式を決める前に 「誰から、何を、どう守るか」 を整理する。これを「脅威モデリング(Threat Modeling)」と呼ぶ。
脅威モデリングの簡易版(STRIDE)
Microsoftが提唱した分類。脅威を6つのカテゴリで網羅的に洗い出す:
略 意味 認証/認可との関係 Spoofing なりすまし 認証で防ぐ Tampering 改ざん 整合性チェック・署名 Repudiation 否認 監査ログ Information Disclosure 情報漏洩 認可・暗号化 Denial of Service サービス妨害 レート制限 Elevation of Privilege 権限昇格 認可の堅牢性 使い方: 設計レビューで「この機能に対する S/T/R/I/D/E はそれぞれ何?」と問う。脳内チェックリストとして優秀。
TaskNote の脅威モデル(演習)
自分のメモに以下を埋めてみる:
- 守りたい資産: ユーザーのタスク内容、メールアドレス、パスワードハッシュ
- 想定攻撃者:
- 外部の野良攻撃者(自動ボット)
- 元従業員(権限剥奪後もアクセスを試みる)
- 内部の悪意あるエンジニア
- 想定攻撃シナリオ:
- パスワードリストでブルートフォース
- SQL Injection でDB直接アクセス
- 他人のタスクIDを推測してURL直叩き(IDOR)
- 対策:
- bcrypt + レート制限 + MFA
- prepared statement + 入力検証
- 各エンドポイントで「このリソースは自分のものか?」をチェック
8. 「ログイン機能を実装する」設計レビュー観点
実装に入る前のチェックリスト:
ログイン機能の最低要件
- パスワードは bcrypt / argon2 で保存(平文・SHA-256単体は論外)
- ログイン試行回数制限(5回失敗で15分ロック等)
- パスワード強度ポリシー(最低8文字、辞書攻撃対策)
- HTTPS 必須(パスワードを平文ネットワークに流さない)
- セッションIDは推測不能(暗号学的乱数)
- セッション固定攻撃対策(ログイン後にセッションID再生成)
- ログアウト機能(サーバー側でセッション破棄)
- パスワードリセットフロー(メール経由、ワンタイムトークン)
- 監査ログ(誰がいつログインしたか)
- MFA オプション(管理者は必須)
練習課題
# 1. 自分のメモ用に空ファイル作成
touch ~/learn/security/day01_auth_design.md
# 2. 以下を埋める
# - 自分の関わるサービス(実在 or 架空)の名前
# - 守りたい資産トップ3
# - 想定する攻撃者トップ3
# - 認証方式の選択(パスワード / SSO / MFA の組合せ)
# - 認可方式の選択(RBAC / ABAC)
# - 設計の弱点として懸念していること設計メモのテンプレ
# TaskNote 認証/認可設計メモ ## 守りたい資産 1. ユーザーのタスク内容(機密度: 中) 2. メールアドレス(機密度: 中) 3. 認証情報(パスワードハッシュ)(機密度: 高) ## 認証方式 - 一般ユーザー: メール+パスワード(bcrypt) - 管理者: 上記 + TOTP MFA 必須 - 将来: Google SSO を追加検討 ## 認可方式 - RBAC: admin / member / guest の3ロール - リソースアクセス: 「自分のチームのタスクのみ」を全エンドポイントでチェック ## 既知の懸念 - パスワードリセットフローのトークン有効期限を未決 - JWT 利用するか、セッション Cookie にするか未決
締め: 振り返り(10分)
1. セッション録画を終了
exit2. 今日の発見(このノートに追記)
- 「認証と認可の違い」を3行で説明できるか書いてみる:
- 自分が普段使っているサービスで、MFAを有効にしていないものは?:
- 脅威モデルを書いてみて気づいた弱点:
- 明日やりたいこと:
チェックリスト
- 「認証」と「認可」を1分で口頭説明できる
- HTTP 401 と 403 の使い分けを言える
- 認証の3要素(知識/所持/生体)を挙げられる
- パスワード/SSO/MFA/トークンの違いを表で書ける
- RBAC と ABAC の違いを言える
- STRIDE の6項目を見ながら自サービスを評価した
-
day01_auth_design.mdに脅威モデルメモを残した
詰まった時のチートシート
| 用語 | 1行説明 |
|---|---|
| Authentication (AuthN) | あなたは誰か確認する |
| Authorization (AuthZ) | この人に X をさせていいか判断する |
| MFA | 異なる要素を2つ以上組み合わせる |
| SSO | 認証を外部 IdP に委譲 |
| OAuth 2.0 | 認可フレームワーク(権限委譲) |
| OIDC | OAuth 2.0 + 認証層 |
| JWT | 署名付きで中身を持ったトークン |
| RBAC | ロールに権限を集約 |
| ABAC | 属性で動的に判定 |
| STRIDE | 脅威分類のチェックリスト |
| 401 | 認証情報が無い/無効 |
| 403 | 認証OKだが認可NG |
「実務OK」基準
- AuthN と AuthZ を絶対に混同しない: コードレビューで他人が混同していたら指摘できる
- 「ログインしたから何でも見える」を許さない: 各エンドポイントで認可チェックを入れる発想がある
- MFA の本質を理解している: 「パスワード + 秘密の質問」が多要素ではない理由を言える
- 設計段階で脅威モデルを考える: 後から塞ぐのではなく最初から守る
メタ認知: 自分の理解度を診断する
30秒セルフテスト
以下を 見ずに口頭で 答えられるか試す。詰まったら本文に戻る。
- 「認証」と「認可」を1文ずつで説明せよ
- パスワード+秘密の質問は「多要素」か? Yes/No と理由
- 401 と 403 の使い分けは?
- SSO の裏で動くプロトコルを2つ挙げよ
- STRIDE の S と E は何? 認証/認可とどう関係する?
2問以上詰まったら → セッション①と③(比較表)を再読。すべて即答できたら次章へ。
次のレッスン
1-2 パスワードハッシュ でパスワード保存の正しい方法(bcrypt / argon2 / salt / pepper)に踏み込む。今回「パスワードはハッシュ化」と言ったが、実は SHA-256 そのままではダメ。なぜ専用のアルゴリズムが要るのかを次回扱う。
1週間後にもう一度ここに戻る(間隔反復)
認証/認可の用語は 1週間後に薄れる。1-6 XSS まで終わったタイミングで、この章の「詰まった時のチートシート」表だけ眺め直すと記憶が定着する。