~/VibeHandbook
$39

18 · 04

認証と認可: 誰でも呼べるエンドポイント

この2つの言葉は似て聞こえるが、その違いこそが本当の侵害が潜む場所だ。

  • 認証 (Authentication)あなたは誰か?——ログインし、身元を証明すること。
  • 認可 (Authorization)あなたは何をしてよいか?——このログイン済みのユーザーが、このデータに対してこの操作を行ってよいかどうか。

AIは認証はそこそこ得意だ。ライブラリがほとんどを処理してくれる。AIが日常的に失敗するのは認可のほうだ。認可はあなたのアプリのルールに固有のもので、AIはそれを知らないからだ。教科書どおりの惨事はこうだ。

// VULNERABLE: ログイン済みかはチェックするが、誰なのかはチェックしない
app.get("/admin/export-all-users", requireLogin, (req, res) => {
  res.json(db.getAllUsers()); // ログイン済みなら誰でもここを叩ける
});

このエンドポイントは「保護されている」——ログインしていなければならない。だがどんなログイン済みユーザーでも、30秒前にサインアップした人を含めて、これを呼んで全ユーザーのデータをダウンロードできる。認証はあり、認可はない。修正方法は、操作そのものに対して権限をチェックすることだ。

// SAFE: このユーザーが本当に管理者かを確認する
app.get("/admin/export-all-users", requireLogin, (req, res) => {
  if (!req.user.isAdmin) return res.status(403).send("Forbidden");
  res.json(db.getAllUsers());
});

同じ罠は、いたるところに小さな形で現れる。注文 #1234 を返すのに、その注文がリクエスト元のユーザーのものかをチェックしないエンドポイント。誰でもURLの数字を変えれば、他人の注文を読める。ルールは地味だが絶対だ。データに触れるすべてのエンドポイントで認可をチェックし、クライアントから来たIDを信用しないこと。 隠されているからといって、隠しURLが安全だと思い込んではいけない——「これが存在することは誰も知らない」はセキュリティ対策ではない。

オフラインでも読みたい?

PDF + EPUB + ダウンロード可能なプロンプトライブラリ + バージョンアップデートを入手しよう。

$ PDFを入手 — $39