TL

認証と認可の違い

認証(AuthN)は「あなたは誰か」、認可(AuthZ)は「あなたは何をしてよいか」。順番も役割も別物で、混同すると「ログインさえすれば全部見える」事故になる。

中級認証認可アクセス制御RBAC最終更新: 2026-06-04
TL;DR要点だけ先に
  • 1.認証(Authentication)=本人確認「あなたは誰か」、認可(Authorization)=権限判定「あなたは何ができるか」。まず認証、次に認可の順で、別々に判断する。
  • 2.混同が事故の元。ログイン済みだから OK とリソースを返すと、他人の ID を指定して他人のデータが見える(IDOR / 権限昇格)。認可は「リソースごとに」毎回確認する。
  • 3.未ログインは 401(Unauthorized=認証不足)、ログイン済みでも権限なしは 403(Forbidden=認可で却下)。権限管理は RBAC(役割で付与)か ABAC(属性で判定)で組む。

なぜ分けて考えるのか

英語の頭がどちらも "Auth" で始まるせいで混同されがちですが、役割はまったく別です。

  • 認証(AuthN):通信してきた相手が本当に本人かを確かめる。ID とパスワード、ワンタイムコード、生体、OIDC などで「この人は確かに user123 だ」と特定する。詳しい仕組みは Web 認証(Cookie・セッション・JWT)
  • 認可(AuthZ):本人だと分かった上で、この操作・このデータへのアクセスを許してよいかを判断する。「user123 は自分の注文は見られるが、他人の注文や管理画面は見られない」を決める。

ここで決定的に大事なのは、認証が通っても認可が自動的に OK になるわけではないということ。ログインは「建物に入れた」だけで、「どの部屋に入れるか」は別問題です。この一段を省くのが、後述の最も多い事故につながります。

“Auth” と略さない

コードやドキュメントで auth とだけ書くと、認証と認可のどちらを指すのか曖昧になります。**AuthN(認証)/ AuthZ(認可)**と書き分けると、設計レビューやレイヤ分割の議論がぶれません。

認証 vs 認可:何が違うか

2つの違いを、観点ごとに並べます。問いの形にすると区別しやすくなります。

観点認証(AuthN)認可(AuthZ)
問いあなたは誰か?あなたは何をしてよいか?
確かめる対象本人かどうか(身元)権限があるか(操作・リソース)
手段の例パスワード / MFA / 生体 / OIDCRBAC / ABAC / ACL / ポリシー
タイミング最初に1回(ログイン時)リクエストごと・リソースごとに毎回
失敗時のHTTP401 Unauthorized403 Forbidden
ひとことで入口で本人確認中で立入許可を判定

「タイミング」の行が実装上の肝です。認証はログイン時にまとめて済ませますが、認可はリクエストのたび、しかも触ろうとしているリソース1件ごとに判定し直す必要があります。

一番多い事故:認可の確認漏れ(IDOR)

OWASP Top 10 で**第1位がアクセス制御の不備(Broken Access Control)**です。その典型が IDOR(Insecure Direct Object Reference=直接オブジェクト参照の不備)。「ログインさえしていればOK」として、そのデータが本当にその人のものかを確認し忘れると起きます。

// ❌ 脆弱:認証は見ているが、認可(持ち主チェック)が抜けている
app.get('/orders/:id', requireLogin, async (req, res) => {
  // ログイン済みなのは確認済み。だが「誰の注文か」を問わずに返してしまう
  const order = await db.orders.findById(req.params.id);
  res.json(order); // /orders/1002 と URL を書き換えれば他人の注文が丸見え
});

ログインユーザーが URL の :id1001 → 1002 と変えるだけで、他人の注文が見えてしまいます。認証は通っているのに認可をしていない、まさに混同の事故です。直し方は、取得したリソースの所有者と、認証で確定した本人が一致するかを必ず照合すること。

// ✅ 安全:認証で確定した本人と、リソースの持ち主が一致するか検証する
app.get('/orders/:id', requireLogin, async (req, res) => {
  const order = await db.orders.findById(req.params.id);
  if (!order) return res.sendStatus(404);
  // req.user.id は「認証」で確定済みの本人。これと突き合わせるのが「認可」
  if (order.userId !== req.user.id) {
    return res.sendStatus(403); // 本人だが、このリソースの権限はない
  }
  res.json(order);
});
「ログイン済み=アクセスOK」は最大の落とし穴

認可で最も多い欠陥は、リソースの持ち主・権限を確認せず、ログインの有無だけで通してしまうことです。/users/123/settings のような ID 入りの URL、?role=admin のようなパラメータ、隠してあるだけの管理用エンドポイントは、いずれもサーバ側で毎回権限を再判定しなければ突破されます。UI でボタンを隠しても、攻撃者は直接 API を叩くのでフロントの非表示はアクセス制御ではありません。判定は必ずサーバ側で行ってください。

401 と 403:どちらを返すか

混同しやすいのが 401403 です。認証で落ちたのか、認可で落ちたのかで使い分けます。

状況ステータス意味クライアントがすべきこと
ログインしていない / トークン無効・期限切れ401 Unauthorized認証が不足(あなたが誰か分からない)ログイン・再認証する
ログイン済みだが権限がない403 Forbidden認可で却下(誰かは分かるが許可がない)再ログインしても無駄(権限が要る)

紛らわしいことに、401 の名前は "Unauthorized" ですが**意味は「未認証(Unauthenticated)」**です。「認証して出直して」が 401、「あなたが誰かは分かっているが、ここは立入禁止」が 403。この区別が HTTP のステータスコード の理解とも噛み合います。

存在を隠したいなら 403 ではなく 404 も選択肢

他人のリソースに 403 を返すと、「その ID は存在する」と攻撃者に教えてしまう(リソース列挙のヒントになる)ことがあります。秘匿性が高い場面では、あえて 404 Not Found を返して存在自体を伏せる設計も有効です。「権限が無いことを正直に伝える(403)」か「存在を隠す(404)」かは、情報漏洩リスクとUXのトレードオフで選びます。

認可の設計:RBAC と ABAC

「誰が何をしてよいか」をどうルール化するかが認可の設計です。代表的なのが RBAC と ABAC の2つ。

  • RBAC(Role-Based Access Control=役割ベース):ユーザーに「管理者」「編集者」「閲覧者」などの**役割(ロール)**を割り当て、役割に紐づく権限でアクセスを決める。「編集者は記事を書ける/閲覧者は読めるだけ」のように、役割の数だけルールを書けばよく、管理がシンプル。多くのアプリの第一選択。
  • ABAC(Attribute-Based Access Control=属性ベース):ユーザー・リソース・状況の属性(部署・所有者・時刻・IP など)を組み合わせたポリシーで判定する。「所有者本人なら編集可」「営業時間内かつ社内ネットワークからのみ可」のような、役割だけでは表せない細かい条件を扱える。
観点RBAC(役割ベース)ABAC(属性ベース)
判定の軸役割(ロール)属性の組み合わせ(誰・何・いつ・どこ)
ルール例admin は削除可、viewer は閲覧のみ所有者かつ営業時間内なら編集可
きめ細かさ粗い〜中(役割単位)細かい(文脈・条件で動的)
管理のしやすさシンプルで運用しやすい柔軟だがポリシーが複雑化しやすい
向いている場面多くの業務アプリ・SaaS の基本規制・マルチテナント・きめ細かい制御

実務ではまず RBAC を土台にし、役割だけでは表せない条件(「自分のデータだけ」など)を属性で補うハイブリッドが現実的です。先ほどの注文の例(order.userId === req.user.id)も、ロールに加えて所有者という属性で絞る ABAC 的な判定でした。

認可は「最小権限」で組む

役割や権限を設計するときは、**最小権限の原則(必要な権限だけを、必要な範囲で与える)を基準にします。「とりあえず admin」を配りすぎると、1アカウントの漏洩が全体の侵害に直結します。デフォルトは拒否(許可したものだけ通す allow-list)**にし、権限は足りなくなってから足すのが安全側です。考え方は 最小権限の原則 も参照。

まとめ:混同しないためのチェックリスト

最後に、設計・レビューで自問すべき点を整理します。

問い見るべきことミスると起きること
相手は本人か?(認証)トークン/セッションの検証・有効期限なりすまし・不正ログイン
このリソースを触ってよいか?(認可)所有者/ロール/属性をサーバ側で毎回判定IDOR・権限昇格(他人のデータ閲覧)
失敗時に正しく返したか?401=未認証 / 403=権限なし(必要なら404)情報漏洩・クライアント側の誤動作

認証と認可は、「誰か」を確かめる工程と「何ができるか」を決める工程という別々のレイヤです。認証が完璧でも認可が抜ければ穴になり、その逆も成り立ちません。具体的な方式の比較は 認証・認可の方式 に、ログイン状態の保持の仕組みは Web 認証 にまとまっています。アクセス制御を「リソースごと・サーバ側・デフォルト拒否」で組む——これが事故を防ぐ一番の近道です。

セキュリティ Article

認証と認可の違いを実務で読む

TL;DRは入口です。実際に選ぶ・使う段階では、何を解決するか、何と比較するか、導入後にどこで詰まるかまで見る必要があります。

解決すること

認証

比較で見る軸

難易度: intermediate / カテゴリ: セキュリティ / タグ数: 4

導入後に効く点

混同が事故の元。ログイン済みだから OK とリソースを返すと、他人の ID を指定して他人のデータが見える(IDOR / 権限昇格)。認可は「リソースごとに」毎回確認する。

先に潰すリスク

用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。

数字・仕様の読み方
難易度
intermediate
カテゴリ
セキュリティ
タグ数
4

判断チェックリスト

  • 自社の用途が「認証 / 認可」に近いか確認する。
  • 強みである「認証(Authentication)=本人確認「あなたは誰か」、認可(Authorization)=権限判定「あなたは何ができるか」。まず認証、次に認可の順で、別々に判断する。」が本当に評価軸になるか確認する。
  • 注意点の「用語だけ覚えても、設計・実装・運用でどこに効くかを確認しないと判断を誤る。」を運用で吸収できるか確認する。
  • 公開値や仕様値は、対象プラン・対象機種・対象リージョンまで確認する。
  • 既存システム、ID、ネットワーク、監視、バックアップとの接続方法を先に洗い出す。
  • 小さく試してから、本番移行、権限設計、障害時手順、コスト監視を決める。

次に確認する観点

認証認可アクセス制御RBAC認証認可アクセス制御RBAC
参考: 公式情報