認証と認可 — 誰かを確かめることと、何を許すこと
「認証」と「認可」はどちらも英語の頭が Auth で始まり、日本語でも一字違いです。混ざったまま設計すると、ログインさえしていれば何でもできるシステムが生まれます。
2 つを分ける基準は単純です。誰であるかを確かめるのが認証、何を許すかを決めるのが認可。
この章で学ぶこと
- 認証と認可の違いと、必ず認証が先に来る理由
- 失敗したときに返すべきステータスコードの違い
- 認証状態をセッションで持つかトークンで持つか
- 認可をどこで判定すべきか
HTTP のステータスコードの分類を前提にします。
この章で扱わないこと
実装の詳細と、データベース設計の観点は既存のガイドが扱います。
| 観点 | 参照先 |
|---|---|
| テーブル設計、パスワード保管、MFA、監査ログ | データベース設計ガイド — 認証・認可システムの設計 |
| 外部サービスとの認証連携 | データベース設計ガイド — OAuth と OpenID Connect |
| SPA でのトークン保管とセッション | React ガイド — SPA の認証 |
| フレームワークでの実装 | Laravel API 開発ガイド — 認証 / 認可 |
認証と認可
| 認証 (Authentication) | 認可 (Authorization) | |
|---|---|---|
| 問い | あなたは誰ですか | それをしてよいですか |
| 確かめるもの | 本人性 | 権限 |
| 例 | ログイン、指紋、ワンタイムパスワード | 管理者だけが削除できる、自分の注文だけ見られる |
| 失敗時 | 401 Unauthorized | 403 Forbidden |
| 順序 | 先 | 後 |
順序が逆になることはありません。誰か分からない相手に何を許すかは決められないからです。
例外に見えるのが匿名アクセスです。ログインせずに公開ページを見られるサイトでは認証が省かれているように見えますが、実際には「匿名という身元」で認可を判定しています。「匿名でも閲覧は許す」という認可のルールが働いています。
ステータスコードの使い分け
紛らわしいのは 401 の名前です。Unauthorized (認可されていない) と書いてあるのに、意味は認証されていないです。仕様上の命名の歴史的な事情で、実際の使い分けは次のとおりです。ステータスコード全体の分類は HTTP で扱っています。
| コード | 状況 | クライアントが取るべき行動 |
|---|---|---|
401 Unauthorized | 資格情報が無い、期限切れ、不正 | ログインし直す |
403 Forbidden | 認証は通ったが権限が足りない | あきらめる。やり直しても同じ |
**401 は「やり直せば通るかもしれない」、403 は「やり直しても通らない」。**この対比で覚えると迷いません。
認証の 3 要素
本人性を確かめる材料は、大きく 3 種類に分かれます。
| 要素 | 内容 | 例 | 弱点 |
|---|---|---|---|
| 知識 (Something you know) | 本人だけが知っていること | パスワード、暗証番号 | 漏れる、推測される、使い回される |
| 所持 (Something you have) | 本人だけが持っているもの | スマートフォン、ハードウェアキー | 盗まれる、紛失する |
| 生体 (Something you are) | 本人の身体的特徴 | 指紋、顔、虹彩 | 変更できない、誤認識がある |
多要素認証 (MFA) は、異なる要素を 2 つ以上組み合わせることを指します。ここが誤解されやすい点で、「パスワード + 秘密の質問」はどちらも知識なので多要素ではありません。両方とも同じ漏洩経路でまとめて破られるためです。
「パスワード + スマートフォンへのコード送信」なら知識と所持なので多要素です。パスワードが漏れても、端末が手元に無ければ突破できません。
認証状態をどう持ち回るか
HTTP はステートレスなので、一度ログインしても次のリクエストでは「誰だか分からない」状態に戻ります。認証済みであることを毎回のリクエストで示す必要があります。
| セッション方式 | トークン方式 | |
|---|---|---|
| 何を渡すか | セッション ID (意味を持たない文字列) | 署名付きトークン (中に情報が入る) |
| 状態の置き場 | サーバー側 (セッションストア) | トークン自体 |
| 失効させる | セッションストアから消せば即座 | 有効期限まで止められない |
| サーバー間の共有 | ストアの共有が要る | 署名鍵さえあれば検証できる |
| 主な運搬手段 | クッキー | Authorization ヘッダー、またはクッキー |
判断の軸は失効の即時性とスケールのどちらを優先するかです。
セッション方式は、サーバーが状態を持つぶん即座に失効させられます。「不正利用が疑われるアカウントを今すぐ止める」が確実にできます。
トークン方式は、サーバーが状態を持たないので水平にスケールしやすくなります。代わりに、いったん発行したトークンは有効期限が来るまで有効です。**この期限は瞬間で表します。**地方時で持つと、解釈するタイムゾーン次第で期限が動きます (日時とタイムゾーン)。これを緩和するために、短命なアクセストークンと長命なリフレッシュトークンを組み合わせ、失効リストを別途持つ設計が使われます。
認可のモデル
権限をどう表現するかにはいくつかの型があります。
| モデル | 考え方 | 向いている場面 |
|---|---|---|
| RBAC (ロールベース) | ユーザーにロールを与え、ロールに権限を紐づける | 組織の役職と権限が対応する場合 |
| ABAC (属性ベース) | ユーザー・リソース・状況の属性から判定する | 「自分の部署のものだけ」など文脈が要る場合 |
| ACL (アクセス制御リスト) | リソースごとに誰が何をできるかを列挙する | ファイル共有のように個別指定が要る場合 |
実務では組み合わせることが多くなります。「管理者ロールなら全件、一般ユーザーなら自分のものだけ」は RBAC と ABAC の混在です。
認可はサーバーで判定する
画面にボタンを表示しないことは認可ではありません。
// これは認可ではない。見た目を整えているだけ
{user.role === 'admin' && <DeleteButton />}
ボタンを隠しても、API を直接叩けば実行できます。ブラウザの開発者ツールでリクエストを組み立てるのは誰にでもできます。認可の判定は必ずサーバー側で行い、クライアント側の出し分けは体験を良くするための補助と位置づけます。
OWASP Top 10:2025 で A01 が Broken Access Control (アクセス制御の不備) であることは、この失敗が今も最も多いことを示しています。典型的な形は次のとおりです。
- URL の ID を書き換えると他人のデータが見える (
/orders/1001を/orders/1002に変える) - 管理用 API に認可チェックが入っていない
- クライアント側だけで権限を判定している
1 つ目は特に頻出で、リソースの所有者と操作者が一致するかをサーバーで必ず確認する必要があります。
記述で答えるときの骨子
認証と認可はどう違うのか、と問われたときの組み立て方です。
- それぞれの定義を 1 文で — 認証は本人性の確認、認可は権限の判定
- 順序を述べる — 認証が先で認可が後。誰か分からない相手に権限は決められない
- 具体例を 1 組 — 「社員証で入館するのが認証、入れる部屋が役職で決まるのが認可」のように、身近な対比を使う
- 技術的な現れ方に触れる — 失敗時のステータスコードが
401と403で分かれる - 実装上の注意を 1 つ — 認可はサーバー側で判定する。画面での出し分けは認可ではない
3 番目の具体例があると、定義の暗記ではなく理解として伝わります。1 から 3 までで基本は満たせるので、時間や字数が限られるならそこまでで区切ります。
よくある誤解
「401 は権限が無いという意味」 — 401 は認証されていない状態です。権限不足は 403 です。名前が Unauthorized なので紛らわしいのですが、実際の使い分けは認証と認可で分かれます。
「パスワードと秘密の質問で多要素認証」 — どちらも知識の要素なので多要素ではありません。異なる要素を組み合わせる必要があります。
「ログインできているなら認可も済んでいる」 — 別です。ログインは「誰か」を確定させただけで、その人に何を許すかは別途判定します。
「管理者にしかボタンを表示していないので安全」 — 表示の制御は認可ではありません。API を直接叩かれれば通ります。
「JWT を使えばログアウトも即座に効く」 — トークン方式は有効期限まで止められないのが原則です。即座に止めたいなら失効リストなどの仕組みを別途用意します。
確認問題
問 1. 次の処理は認証と認可のどちらですか。
A. ワンタイムパスワードの照合
B. 「この注文は自分のものか」の確認
C. パスワードのハッシュ値の照合
D. 「管理者ロールを持っているか」の確認
E. 指紋の読み取り
答え:
| 分類 | 理由 | |
|---|---|---|
| A | 認証 | 所持の要素で本人性を確かめている |
| B | 認可 | 誰かは既に分かっていて、そのリソースへの権限を判定している |
| C | 認証 | 知識の要素で本人性を確かめている |
| D | 認可 | 権限の判定 |
| E | 認証 | 生体の要素で本人性を確かめている |
判別の問いは「本人かどうかを調べているか、してよいかを調べているか」です。A・C・E は身元の確認、B・D はその後の権限判定です。
B は見落とされやすい認可です。「ログインしているから自分の注文だ」と決めつけると、ID を書き換えて他人の注文が見える不備になります。
問 2. API が 403 Forbidden を返しました。クライアントはログイン画面へ遷移させるべきですか。
答え: させるべきではありません。
403 は「あなたが誰かは分かっているが、それをする権限が無い」という意味です。ログインし直しても同じユーザーなら結果は変わりません。ログイン画面へ飛ばすと、ユーザーは何度ログインしても同じエラーに遭遇します。
正しい対応は、権限が無い旨を伝えて別の導線を出すことです。
| コード | 対応 |
|---|---|
401 | ログイン画面へ。トークンの更新を試みる |
403 | 「権限がありません」と表示。管理者への申請導線があれば案内する |
逆に、トークンの期限切れで 403 を返している API があると、クライアントは再ログインすべき状況を判別できません。サーバー側でこの 2 つを正しく返し分けることが前提になります。
問 3. 面接で「認証と認可はどう違いますか」と聞かれました。3 文で答えてください。
解答例:
認証は「その人が本人であるか」を確かめる処理で、パスワードや生体情報などで身元を確定させます。認可は「その人にその操作を許すか」を判定する処理で、ロールや所有関係をもとに権限を決めます。認証が先で認可が後という順序があり、誰か分からない相手に何を許すかは決められないためです。
要素の対応は次のとおりです。
| 文 | 含めた要素 |
|---|---|
| 1 文目 | 認証の定義 + 手段の例 |
| 2 文目 | 認可の定義 + 判定材料の例 |
| 3 文目 | 順序 + その理由 |
余裕があれば「失敗時は認証が 401、認可が 403」を足すと、技術的な理解まで示せます。逆に**定義だけを 2 文並べて終わると、暗記との区別が付きません。**順序とその理由が入っているかが分かれ目です。
まとめ
- 認証は「誰であるか」の確認、認可は「何を許すか」の判定です
- 認証が先で認可が後。順序が逆になることはありません
- 失敗時は認証が
401、認可が403。401はやり直せば通るかもしれない、403はやり直しても通らない、という違いです - 認証の要素は知識・所持・生体の 3 つ。多要素認証は異なる要素の組み合わせで、同じ要素を 2 つ重ねても多要素ではありません
- セッション方式は即座に失効させられ、トークン方式はスケールしやすい。トークンは有効期限まで止められないのが原則です
- **認可はサーバー側で判定します。**画面での出し分けは認可ではありません
- OWASP Top 10:2025 の A01 は Broken Access Control です
- データベース設計ガイド — 認証・認可システムの設計 — パスワード保管・セッション・MFA・監査ログの設計
- データベース設計ガイド — OAuth と OpenID Connect — 外部サービスとの認証連携
- React ガイド — SPA の認証 — トークンの保管場所と XSS・CSRF 対策
- OWASP Top 10:2025
次に読む
- Web アプリの主要な攻撃と対策 — 認可の不備が最多である理由と、その他の攻撃