メインコンテンツへスキップ

ログインの先で、権限を確かめる

別の端末でも読書メモを開く拡張では、利用者と記録を対応させます。自分のメモが読めることに加え、他人のメモを読めず、変えられないことを確かめます。

  • レッスン 8 / 12
  • 19分

このレッスンで

終わる頃には、次ができるようになります

  • 認証と認可:誰なのかと、何を許すか
  • 二人で試す:拒否されることも成果にする

別の端末でも読書メモを開く拡張では、利用者と記録を対応させます。自分のメモが読めることに加え、他人のメモを読めず、変えられないことを確かめます。

この回は、しくみを読むことと、実際の結果を確かめる練習を組み合わせます。付属見本はブラウザーだけで保存する一人用の版です。アカウント・データベース・共有は拡張課題として扱います。

別の端末でも読書メモを開く拡張では、利用者と記録を対応させます。自分のメモが読めることに加え、他人のメモを読めず、変えられないことを確かめます。
概念を表す生成挿画。製品の実画面ではありません。

認証と認可:誰なのかと、何を許すか

一人用の読書メモが使えるようになり、スマートフォンにも同じ一覧を出したくなりました。ここから先は、アカウントとデータベースを使う拡張です。一人用の版を置き換える必要はありません。別の練習環境で、利用者AとBという架空の二人を用意し、それぞれの読書メモを保存する設計を考えます。

認証は、利用者の身元を確かめることです。認可は、その利用者に、ある操作を許すか判断することです。Aとしてログインできたからといって、Bのメモも読めるわけではありません。ログイン画面を追加した後も、一件ごとの閲覧、編集、削除にどんな条件を付けるかを決めます。資料 AUTHZ

この拡張では、読書記録にownerIdを持たせます。記録を追加した人を示す値です。idはメモそのものを区別し、ownerIdは持ち主を区別します。更新できるのは、認証された利用者のIDと記録のownerIdが一致するときです。書名や、画面に出した表示名で持ち主を判定しないようにします。

本人確認の後に、持ち主を照合する

ログインした利用者と、記録のownerIdを受け取る側で照合します。画面が操作を隠していても、保存先で許可の条件を適用します。

認証済みのAに許す操作の範囲
  • Aの記録を取得、追加、更新、削除
範囲の外
  • Bの記録と、未ログインからの操作
  • 記録のidと持ち主のownerIdは、役割が違います。
  • 一覧と一件の操作の両方で権限を確かめます。
ログインした利用者と、記録のownerIdを受け取る側で照合します。画面が操作を隠していても、保存先で許可の条件を適用します。

持ち主の値を、送信されたまま信用しないことも必要です。AのブラウザからBのownerIdを送れば、Bの記録にできる実装では困ります。サーバーが確認した利用者から値を決めるか、保存先が一致を検査します。依頼する側が自由に書ける情報と、受け取る側が確かめた情報を分けましょう。

ボタンを隠すだけでは、この約束を守れません。画面に削除ボタンがなくても、APIへ直接削除の依頼を送れる場合があります。OWASPは、画面側の判断だけにアクセス制御を任せず、サーバー側などで確認するよう求めています。読書メモでは、一覧の取得も、一件の更新も、受け取る場所で権限を確かめます。資料 AUTHZ

Supabaseを使う場合は、データベースの行ごとに条件を適用するRLSを使えます。ログインした利用者が、自分の行だけを読む条件を設定します。読み取り、追加、更新、削除はそれぞれ確認します。RLSを有効にしたという事実だけで受け取らず、テーブルへの権限と条件が組み合わさっているかを見ます。資料 RLS

許可する範囲は、最初に短い表で決めます。AはAの記録を読み、追加し、変え、消せる。BもBの記録だけを扱える。ログイン前はどちらの記録も扱えない。この本の拡張は、この約束に絞ります。公開のおすすめ本や共同の読書会を作る場合は、新しい許可として別に設計します。

ログイン後の状態を保つ仕組みは、セッションです。画面上に名前が出ていることだけを本人確認の根拠にしません。受け取る側が有効な認証情報を確認します。ログアウトや期限切れも起きるので、保存操作の途中で利用できなくなったときには、拒否と入力の扱いが分かる表示を用意します。資料 AUTHN

初めての実装では、パスワード管理を自作する範囲を増やすより、提供された認証の仕組みを理解して使う方が進めやすくなります。それでも、誰にどの記録を許すかはアプリ側で決めます。AIに『ログインを付けて』とだけ頼まず、AとBでできること、できないことを具体的に伝えます。

認証の依頼に、許可条件を添える

読書メモのアカウント付き版を別の練習環境で設計します。AとBは自分の記録だけを扱えます。
ownerIdは認証された利用者と対応させます。クライアントから別のownerIdが送られても、他人の記録を作ったり変えたりできないようにします。
一覧取得、追加、更新、削除の各操作で、どこが権限を確認するかを説明してください。

手を動かす順番

  • 認証と認可を別の条件として書く
  • 記録と持ち主のIDを対応させる
  • サーバーやデータベースで許可条件を適用する
  • 未ログインと期限切れの扱いを決める

二人で試す:拒否されることも成果にする

Aが自分のメモを読めたら、半分の確認ができました。次はBとして、Aの記録へ触れないことを試します。この検査は、自分で用意した練習環境と練習アカウントだけで行います。ほかのサービスや他人のアカウントに同じ操作を向ける必要はありません。許可する結果と、拒否する結果を並べます。

AとBは、別のブラウザプロファイルなど、認証状態が混ざらない場所で使います。Aでメモを一件、Bで別の一件を登録し、各一覧に自分のものだけが出るか確認します。同じブラウザで名前だけ切り替えても、前の認証情報やデータが残れば検査になりません。どちらの本人確認が使われているかも確かめます。

一覧に出ないだけでは、閲覧を防いだ証拠になりません。BからAの記録のidを指定して取得できるか、編集や削除を依頼できるかも試します。追加時にownerIdをAへ変えた場合も確認します。OWASPは、推測できるIDへのアクセスも含め、要求ごとの権限検査と、その検証を勧めています。資料 AUTHZ

許可と拒否を、AとBで照合する

行は操作する人、列は記録の持ち主です。自分の記録は扱え、他人の記録は取得も変更もできないという約束を、実際の操作で検証します。

記録の持ち主

操作する人Aの記録Bの記録
利用者AAからA:許可AからB:拒否
利用者BBからA:拒否BからB:許可

表は横にスクロールできます

  • 各組合せで取得、更新、削除を確認します。追加時のownerIdも照合します。
  • 管理用の鍵ではなく、利用者の権限で試します。未ログインも別に確認します。
行は操作する人、列は記録の持ち主です。自分の記録は扱え、他人の記録は取得も変更もできないという約束を、実際の操作で検証します。

拒否の形は実装によって違います。403などの状態番号を返す場合も、見える行がないという空の結果になる場合もあります。番号だけを合格条件にせず、他人の内容を取得できず、更新も削除も起きていないかを照合します。操作後にAへ戻り、元のメモが変わっていないことまで確認します。資料 RLS

この試験では、利用者が使う権限で操作します。管理用の秘密鍵を使った通信が成功しても、AとBの利用を検査したことにはなりません。Supabaseのsecret keyや旧service_roleのような強い鍵は、RLSを回避する権限を持ちます。ブラウザへ渡さず、必要な管理処理だけで扱います。資料 KEYS

一方、Supabaseのpublishable keyは、ブラウザなどへ公開して使うための設定です。利用者本人の認証は別に行い、データへのアクセスは権限とRLSで制限します。『キーという名前だから全部秘密』とも、『画面で使えたから全部公開してよい』とも判断しません。公式資料で、その値の種類と権限を確認します。資料 KEYS

秘密の値を環境変数へ移しても、ブラウザへ組み込む設定なら利用者から見える場合があります。隠す場所の名前だけで判断せず、どのプログラムへ渡り、どこで実行されるかを調べます。AIへは値を貼らず、設定名、用途、サーバー専用かどうかを尋ねます。画面やログに秘密の値を出さないことも確認します。

漏れた疑いがある秘密の値は、ソースから消しただけでは十分に扱えません。共有した履歴、配布したファイル、ログに残った可能性を考え、提供元の手順で失効と再発行を行います。練習では本物の鍵を載せず、何を停止し、誰が変更し、変更後に何を確認するかという手順だけを残します。

検査の記録には、利用者、操作、対象の持ち主、期待する結果、実際の結果を置きます。Aの読取りは許可、BからAの更新は拒否、未ログインの取得も拒否。この記録があれば、あとから機能を足した際に同じ約束を再確認できます。自分の操作が通ることと、他人の操作が止まることを一組で受け取ります。

拒否を確認する検証表

AでAの一件を取得し、更新できる。Bから同じidを指定しても、内容を取得できず更新できない。
BからAの一件を削除しても、Aに戻ると元の記録が残っている。未ログインでは個人の一覧を取得できない。
利用者用の認証で試し、管理用の鍵を使っていないことを確認する。秘密の値は記録に残さない。

手を動かす順番

  • AとBの認証状態を分ける
  • 各自の記録で正常な操作を確かめる
  • 他人のidを指定した操作と未ログインを試す
  • 拒否の後も元データが変わらないか照合する

演習:自分のメモは扱え、他人のメモは扱えない

アカウント付き版を作る場合の検証表を作成します。まだ実装していない場合は、予定と実行済みを区別し、設計した条件を成果物にします。

  • A、B、未ログインの三状態について、一覧取得と一件の取得、更新、削除の期待結果を書く。
  • 追加時に別のownerIdを送った場合の期待結果を決める。
  • 権限を確認する場所と、ブラウザへ渡す設定の種類を説明する。
  • 検証した操作だけに実際の結果を記入し、元データが保たれたかを照合する。
解答例を読む

AはA、BはBの記録だけを扱います。他人の記録と未ログインからの個人データ取得は拒否します。

送られたownerIdだけを信用せず、確認された利用者に対応する記録として作成するか、違う値の依頼を拒否します。

権限はサーバーやデータベースで適用します。公開用の設定と管理用の秘密鍵を分け、後者をブラウザへ渡しません。

403や空の結果だけで終えず、内容が漏れず、更新や削除も起きていないことを元の利用者で確認します。未実行の項目は未実行のまま残します。

この回で確かめること

  • A、B、未ログインの三状態について、一覧取得と一件の取得、更新、削除の期待結果を書く。
  • 追加時に別のownerIdを送った場合の期待結果を決める。
  • 権限を確認する場所と、ブラウザへ渡す設定の種類を説明する。
  • 検証した操作だけに実際の結果を記入し、元データが保たれたかを照合する。

次の回:動く、を確かめる

参考資料

このレッスンは役に立ちましたか?