コンテンツへスキップ
DedicatedPHP 接触

PHPアプリケーションで委任権限を設計する方法

認証情報を共有せずに操作を委任するためのガイドです。本人、権限範囲、有効期間を定め、操作ごとに認可し、追跡可能性を保ちます。

実行者、代理される本人、権限範囲、監査ログの関係を示すPHPアプリケーションの図

ある人が別の人に代わってタスクを管理できれば、現実のビジネスニーズを解決できます。しかし、パスワードの共有やアカウントへの包括的なアクセス許可を伴うべきではありません。PHPアプリケーションで安全に委任するには、誰が操作し、誰を代理し、どのリソースに対して何ができ、どの期間有効なのかを明確にする必要があります。また、委任は取り消し可能で、監査できなければなりません。

目的は、双方の本人性を保ちながら、具体的な操作を認可することです。そのためには、権限を付与する画面だけでは不十分です。データモデル、すべての認可箇所、非同期処理、テストにも関わります。これらをまとめて設計すれば、ある画面では有効な委任が、別の経路から過剰なアクセスにつながるリスクを減らせます。

委任、なりすまし、共有アクセスを区別する

委任、なりすまし、共有アクセスを区別する — guía visual de DedicatedPHP

委任では、操作を開始する人が引き続き認証済みの本人です。さらに、限定された許可のもとで別の人を代理して操作していることをアプリケーションに記録します。代理される本人はログインしておらず、リクエストの直接の実行者として記録してはなりません。

なりすましでは、システムがリクエストを処理する際の実効的な本人性が切り替わります。専用の制御を実装しないと、誰が操作したのかが見えなくなるおそれがあります。認証情報の受け渡しなどによる共有アクセスは、ユーザー間の区別をなくし、権限の取り消しや操作の帰属を難しくします。通常の委任フローでは、いずれの方法も、実行者と代理される本人を明示するコンテキストの代わりにはなりません。

コードとログでは、両方の役割に名前を付けましょう。たとえば、actor_idは操作を実行した人を、principal_idはその人が代理した本人を示します。どちらを指すのか曖昧になり得るログで、user_idのような名前を使うのは避けてください。

実装前に権限範囲、リソース、有効期間を定める

有用な委任では、何が許可されるのかを正確に記述します。「アカウントを管理する」では範囲が広すぎることがよくあります。代わりに、タスクの確認、状態の更新、リクエストへの返信といった操作に限定できます。操作ごとに影響が異なる場合は、閲覧、編集、承認、削除を汎用的な権限にまとめず、個別の権限としてモデル化します。

リソースの範囲も定めます。組織、プロジェクト、タスク一覧、または特定のレコード群などが該当します。あるプロジェクトのタスクを編集する権限があるからといって、同じ委任先ユーザーが別の機能で別プロジェクトにアクセスできることを理由に、そのプロジェクトのデータ閲覧まで許可してはなりません。

有効期間には明確な開始日時と終了日時を設け、期限前に委任を取り消せる状態も用意します。日付の表示に使うタイムゾーンを決め、内部の比較方法に一貫性を持たせます。承認を必須とする場合や、委任の連鎖を禁止する場合は、明示的に検証可能なルールにしてください。画面上の慣例に委ねてはいけません。

認可をモデル化し、操作ごとに検証する

リレーショナルスキーマでは、委任を識別子、認可された実行者、代理される本人、範囲、操作、開始日時、有効期限、状態、作成者、取り消し日時などのフィールドで表現できます。具体的な構造はドメインによって異なります。操作を関連テーブルや別の検証済み形式で保存する場合もありますが、曖昧な解釈をせずに参照・検証できなければなりません。

認可では、本人自身の権限と、実行者に委任された権限を区別します。要求された操作について、まず代理される本人が通常のアクセス権を持ち、適用されるビジネスルールが操作を許可していることを確認します。次に、認証済みの実行者が有効かつ取り消されていない委任の受取人であり、その委任が該当するリソースに対する操作を許可していることを検証します。実効権限は、本人のアクセス権と委任の範囲の両方に制限されます。委任によって、本人が許可できる操作やリソース、または委任自体に記載された範囲を超える権限を実行者に与えることはできません。実行者自身もそのリソースにアクセスできることを要求してはいけません。委任によって操作できることが、まさにその理由です。ただし、認証、必要なコンテキストへの所属、操作に関するセキュリティ制御など、実行者の本人性に適用される制約は適用してください。

実際の検証には、次の項目を含めます。

  • 実行者が認証済みで、委任の対象者であること。
  • 代理される本人がそのコンテキストで有効であり、要求されたリソースへの通常のアクセス権を持つこと。
  • 操作時点で委任が有効で、取り消されておらず、有効期間内であること。
  • 要求された操作とリソースが付与された範囲内にあり、本人の権限を超えないこと。
  • 実行者および操作に適用されるビジネス上・セキュリティ上の制約を満たすこと。

この判定は、コントローラーに部分的な条件を繰り返し記述するのではなく、認可サービスや再利用可能なポリシーに集約します。それでも、関連するすべての操作で呼び出してください。保護された画面があっても、API、ダウンロード、一括操作、管理用ルートが自動的に保護されるわけではありません。PHPでは、コントローラーが認証済みの実行者を取得し、委任コンテキストを解決してから、対象リソースに対する操作を認可サービスに問い合わせられます。重大な影響を伴う操作では、ドメイン層でも重要な不変条件を強制できます。

ブラウザーから送られたprincipal_idを、認可の根拠として信頼してはいけません。サーバーは、信頼できるデータを使って、実行者、本人、委任、リソース、操作の関係を検証する必要があります。また、画面上のボタンを隠せば、エンドポイントの直接呼び出しを防げると考えてはいけません。

監査と非同期処理で操作の帰属を保つ

有用なログがあれば、本人性を混同せずに何が起きたかを再構成できます。重要なイベントごとに、実行者、代理される本人、操作、リソースの種類と識別子、日時、結果、適用された委任への参照を保存します。リスクに応じて、操作理由や相関IDも記録します。履歴には、秘密情報や不要な個人データを保存しないでください。

帰属情報は、キューやバックグラウンドジョブでも維持しなければなりません。委任によるリクエストがタスクを登録する場合、メッセージには実行者、本人、認可への参照を含む検証可能なコンテキストを渡します。利用できなくなるWebセッションに依存してはいけません。ジョブの実行時に委任が引き続き有効か再検証するかを決めてください。まだキャンセル可能な操作では、実行時に検証することで、取り消し後も古い権限でタスクが残るのを防げることが多くあります。操作がすでに取り消し不能な形で確定している場合は、その境界を文書化し、認可された時点を記録します。

ログを不正な変更から保護し、閲覧できる人を制限します。監査は調査や説明責任を支援するものであり、運用データを無差別に複製するものではありません。

有効期限と取り消しをフローの一部として設計する

有効期限と取り消しは、画面上の状態変更だけではありません。委任コンテキストを保持したセッションには古い選択肢が表示され続けることがあります。そのため、画面も更新しつつ、サーバー側の認可では各リクエストで現在の状態を確認しなければなりません。権限をキャッシュする場合は、無効化の方法と、取り消しが有効になるまで許容する最大遅延を定めます。

取り消し時には、誰がいつ実行したかを記録します。関連するアクティブセッション、発行済みトークン、キュー内のジョブ、一時リンクを明示的に評価してください。セッションの終了やデータベースの値の変更だけで、これらすべてが自動的に無効になると考えてはいけません。適切な対応は設計によって異なりますが、フローを公開する前に決めておく必要があります。

見落とされやすい境界条件をテストする

テストでは、許可される操作と拒否される操作の両方を検証します。少なくとも、未開始、有効期限切れ、取り消し済みの委任、認可されていない実行者、範囲外のリソース、許可されていない操作、本人の誤りまたはリソースへの通常アクセス権がないケース、画面に表示されないエンドポイントへの直接アクセスを含めます。さらに、実行者自身にはリソースへのアクセス権がないものの、本人にはアクセス権があり、委任が操作とリソースをカバーする肯定ケースも含めます。これにより、実行者自身の権限と委任された権限をシステムが混同しないことを確認できます。

時間境界、同時変更、間接的な影響もテストに加えます。たとえば、進行中の操作や保留中のジョブがある間に委任が取り消された場合に何が起きるか、タスクに対する操作が通知、エクスポート、二次的な変更を引き起こすかを確認します。それらの影響でも正しい帰属が維持され、範囲が拡大しないことを検証してください。

認可ポリシーの単体テストと、ルート、永続化、キューを通る統合テストを分けます。判定メソッドだけを検証するテストでは、すべてのルートがそのメソッドを呼び出すことは証明できません。画面のテストも、サーバーが保護されていることの証明にはなりません。

公開前のチェックリスト

公開前のチェックリスト — guía visual de DedicatedPHP
  • コード、画面、監査ログで、実行者と代理される本人を明確に区別しているか。
  • 各委任で操作、リソース、有効期間を限定し、無効な組み合わせを禁止しているか。
  • ポリシーが本人のアクセス権を確認し、実行者自身のアクセス権を要求せずに、委任範囲内に権限を制限しているか。
  • サーバーの各操作で、本人性、状態、期間、範囲、操作を検証しているか。
  • 定められたポリシーに従い、取り消しがセッション、トークン、キャッシュ、保留中のジョブに反映されるか。
  • 不要な情報を保存せずに、操作の帰属をログから確認できるか。
  • 拒否ケース、時間境界、実行者自身にアクセス権がない有効な委任、間接的な影響をテストしているか。

委任が安全なのは、他人のアカウントへのアクセスと混同されず、各操作を本人の権限と有効かつ限定された委任によって正当化できる場合です。誰が、誰に代わって、どのリソースに対し、どの権限で操作したのかをチームが正確に説明できないなら、本番投入前にフローをさらに設計する必要があります。

これらのアイデアをあなたのプロジェクトに活用してみませんか?あなたのPHPプラットフォームについて話し合いましょう。
関連サービスを見る