認証と認可

認証と認可とは

  • 認証(Authentication) = あなたは誰? を確認すること(ログイン)
  • 認可(Authorization) = あなたに何を許可するか? を決めること(権限)

似た言葉ですが役割はまったく別物です。「認証は身分証の確認、認可は入室許可」と例えられます。

混同するとこう壊れる

初学者が最初に踏む地雷は、ログインできた人なら何をしてもよいと扱ってしまう実装です。

注文詳細ページの URL が /orders/1234 だとします。ログイン中の利用者が数字を 1235 に書き換えたとき、他人の注文が表示されてしまう — 「ログイン済みかどうか」しか見ていないと必ず起きる事故です。認証は通っている(本物の利用者ではある)のに、認可が抜けている状態です。正しくは「ログイン済みか」に加えて「その注文はこの利用者のものか」まで毎回確認します。

この種の欠陥は、画面を普通に操作している限り再現しないのが厄介なところです。自分の注文しか一覧に出てこないからです。URL やリクエストの中身は利用者が自由に書き換えられる前提で、サーバー側の判定を点検してください。

ログインの前後で起きていること

「認証」と一口に言っても、実際には次の段階に分かれています。個々の技術がどこを担当しているのかを意識すると、仕組みの位置づけが一気に見通せます。

  1. 識別 — 誰だと名乗ったか(メールアドレスなど)
  2. 認証 — その名乗りが本物かを確かめる(パスワードの照合、追加要素の確認)
  3. 状態の維持 — [[HTTP]] はリクエストごとに記憶を持たないため、「ログイン中」を別の仕組みで覚える
  4. 認可 — 個々の操作について、許可してよいかを判定する
  5. 記録 — 誰がいつ何をしたかを残す([[ログ設計]])

見落としやすいのは、3 と 4 がリクエストのたびに繰り返されることです。ログイン時に一度チェックすれば終わり、ではありません。

初学者向けポイント

  • パスワードはハッシュ化して保存する(平文保存は重大事故のもと)
  • ログイン状態の維持には セッション(Cookie)トークン(JWTなど) を使う
  • すべての通信は [[HTTPS・TLS]] が前提。トークンが盗まれれば本人になりすませてしまう

よく出る仕組み

仕組み概要
セッションCookieサーバーがセッションIDを発行しCookieで管理。伝統的で堅実
JWT署名付きトークンに情報を埋め込む。[[REST API]] と相性がよい
OAuth 2.0「Googleでログイン」のような権限の委譲の標準
多要素認証(MFA)パスワード+確認コードなど複数要素で認証を強化

認可の3つの考え方

認可の判定基準は、大きく次の3種類に整理できます。

考え方判定の基準
所有者チェック対象データの持ち主かどうか「この注文は本人のものか」
ロールベース(RBAC)割り当てられた役割「管理者ロールなら削除できる」
属性ベース(ABAC)利用者・対象・状況の属性の組み合わせ「同じ部署で、かつ勤務時間内なら」

最初は所有者チェックとロールベースの2つで十分です。属性ベースは柔軟ですが、条件が増えるほど「なぜこの人に許可が出たのか」を後から説明しにくくなります。ロールも同じで、例外対応のたびに新しいロールを足していくと、利用者数とほぼ同じ数のロールが並ぶ状態に行き着きます。ロールが人単位に近づいてきたら設計を見直す合図です。

設計の基本原則

  • 最小権限の原則: 必要最低限の権限だけを与える
  • 認可チェックはサーバー側で必ず行う(フロントの表示制御だけでは守れない)

ここから先の読み進め方

認証と認可は入口が広く、どこから手を付けるか迷いやすい領域です。目的別に4つの群へ整理しました。

本人確認を固める

「本当に本人か」を強くする段階です。サーバー側の守りが [[パスワードの保存とハッシュ化]]、利用者側の守りが [[多要素認証]] で、この2つは補完関係にあります。両者の土台になる「戻せない変換」と「戻せる変換」の違いは [[暗号化の基礎]] で整理できます。

ログイン状態を運ぶ

認証そのものは一瞬ですが、その結果は以降のすべてのリクエストで参照されます。サーバー側に状態を置くのが [[セッション管理]]、トークン自体に情報を持たせるのが [[JWT]] で、即時ログアウトのしやすさとスケールしやすさのトレードオフになります。自前でパスワードを預からず外部のログインに委ねるなら、[[OAuth・OIDC]] が標準の入口です。

権限を設計する

「誰に何を許すか」を具体的なルールへ落とす段階です。判断の指針が [[最小権限の原則]]、クラウド上での代表的な実装が [[AWS IAM]]、データベースの行単位まで踏み込んだ形が [[Row Level Security(RLS)]] です。アプリのコードではなくDB側で強制できると、認可の書き忘れが構造的に起きにくくなります。

運用で守り続ける

権限と認証情報は、与えた瞬間から古びていきます。有効期限を短くして漏えい時の被害を抑えるのが [[短期クレデンシャル]]、「社内ネットワークだから安全」という前提を捨てる設計思想が [[ゼロトラスト]] です。認証処理を各サービスに散らさず入口で一括処理する構成は [[APIゲートウェイ]]、認証機能そのものを外部に任せる選択肢は [[BaaS(Backend as a Service)]] にまとまっています。

関連技術とのつながり

  • [[HTTPS・TLS]] — 認証情報を安全に運ぶ土台
  • [[REST API]] — トークンによるAPI保護の主戦場
  • [[Webセキュリティ]] — 認証まわりは攻撃の主要ターゲット
Q: ログイン中の利用者がURLの `/orders/1234` を `1235` に書き換えると他人の注文が見えてしまう。抜けているのはどれ?
- [ ] 認証(本人かどうかの確認)
- [x] 認可(その操作を許してよいかの判定)
- [ ] 通信の暗号化
解説: 本物の利用者としてログインできている以上、認証は通っています。「その注文はこの利用者のものか」という認可の確認が抜けている状態です。

Q: 認証したあとに「ログイン中」を覚える仕組みが必要になる理由はどれ?
- [ ] パスワードをハッシュ化すると元に戻せなくなるから
- [x] HTTPがリクエストごとに記憶を持たないから
- [ ] ロールベースの認可では役割を保存できないから
解説: HTTPは各リクエストが独立しているため、セッションやトークンで認証結果を持ち回る必要があります。

Q: 「この注文は本人のものか」を確かめる認可の考え方はどれ?
- [x] 所有者チェック
- [ ] ロールベース(RBAC)
- [ ] 属性ベース(ABAC)
解説: 対象データの持ち主かどうかで判定するのが所有者チェックです。ロールベースは割り当てられた役割、属性ベースは利用者や状況の属性の組み合わせで判定します。