権限ポリシーによるブラウザ機能の管理

ページとページ上のサードパーティの iframe がブラウザ機能にどのようにアクセスできるかを管理します。

Kevin K. Lee
Kevin K. Lee

権限ポリシー(旧称「機能ポリシー」)を使用すると、デベロッパーはブラウザに適用する一連のポリシーを宣言することで、ページ、その iframe、サブリソースで使用できるブラウザ機能を制御できます。これらのポリシーは、レスポンス ヘッダーの送信元リストで指定された送信元に適用されます。オリジンリストには同一オリジンやクロスオリジンを登録でき、デベロッパーはファースト パーティとサードパーティによるブラウザ機能へのアクセスを制御できます。

ユーザーはより強力な機能へのアクセスを許可する最終決定を下します。そのため、プロンプトを介して明示的な権限を付与する必要があります。

権限ポリシーにより、トップレベル サイトでそのサイトとその第三者が使用する内容を定義でき、ユーザーが機能へのアクセス リクエストが正当かどうか判断する負担が軽減されます。たとえば、権限ポリシーですべてのサードパーティに対して位置情報機能をブロックすることで、サードパーティはユーザーの位置情報にアクセスできません。

権限ポリシーの変更

権限ポリシーは、以前は「機能ポリシー」と呼ばれていたものです。主なコンセプトは同じですが、名称とともにいくつかの重要な変更点があります。

構造化フィールドの使用

構造化フィールドは、HTTP ヘッダー フィールド値の解析とシリアル化を標準化するための一般的なデータ構造のセットを提供します。構造化フィールドについて詳しくは、Fastly のブログ投稿「構造化ヘッダー フィールドで HTTP を改善する」をご覧ください。

古い
  geolocation 'self' https://example.com; camera 'none'

機能ポリシーについて説明します。

新規
  geolocation=(self "https://example.com"), camera=()

権限ポリシーが追加されました。

ヘッダーを iframe allow 属性と組み合わせる

Feature Policy を使用してクロスオリジン フレームに対象物を追加するには、ヘッダーのオリジン リストにオリジンを追加するか、iframe タグに allow 属性を追加します。権限ポリシーにより、オリジンリストにクロスオリジン フレームを追加する場合は、そのオリジンの iframe タグに allow 属性を含める必要があります。 レスポンスに Permissions Policy ヘッダーが含まれていない場合、送信元リストにはデフォルト値の * があるとみなされます。iframe に allow 属性を追加すると、対象物にアクセスできるようになります。

したがって、デベロッパーはレスポンスに Permissions Policy ヘッダーを明示的に設定して、allow が存在しても、オリジンのリストにないクロスオリジンの iframe はこの機能にアクセスできないようにすることをおすすめします。

機能ポリシーは Chrome 88 以降も使用できますが、権限ポリシーのエイリアスとして機能します。構文以外は、ロジックに違いはありません。権限ポリシー ヘッダーと機能ポリシー ヘッダーの両方を使用すると、Permissions-Policy ヘッダーの優先度が高くなり、Feature-Policy ヘッダーで指定された値が上書きされます。

権限ポリシーを使用するにはどうすればよいですか?

概要

詳細に入る前に、あなたがウェブサイトの所有者で、サイトとサードパーティのコードがどのようにブラウザ機能を使用するかを制御したいという一般的なシナリオを見てみましょう。

  • お客様のサイトは https://your-site.example です。
  • サイトに同一オリジン(https://your-site.example)の iframe が埋め込まれています。
  • 信頼できる https://trusted-site.example の iframe がサイトに埋め込まれています。
  • また、https://ad.example が配信する広告も表示されます。
  • サイトと信頼できるサイトのみに位置情報を許可し、広告には許可したくない。

この場合、次のヘッダーを使用します。

Permissions-Policy: geolocation=(self "https://trusted-site.example")

さらに、信頼できるサイトの iframe タグに allow 属性を明示的に設定します。

<iframe src="https://trusted-site.example" allow="geolocation">

権限ポリシーの使用方法を示す簡単な概要図。

この例では、ヘッダー送信元リストにより、サイト(self)と trusted-site.example のみが位置情報機能を使用できます。ad.example は位置情報を使用できません。

  1. お客様のサイト your-site.example は、ユーザーの同意を得たうえで位置情報機能の使用が許可されています。
  2. 同一オリジンの iframe(your-site.example)では、allow 属性を使用しなくてもこの機能を使用できます。
  3. 元のリストに追加されていない別のサブドメイン(subdomain.your-site-example)から配信された iframe で、iframe タグで allow 属性が設定されている場合は、この機能を使用できません。異なるサブドメインは、同一サイト、クロスオリジンと見なされます。
  4. オリジンリストに追加され、iframe タグで allow 属性が設定されているクロスオリジン iframe(trusted-site.example)では、この機能を使用できます。
  5. 送信元リストに追加されたクロスオリジンの iframe(trusted-site.example)で allow 属性が指定されていない場合、この機能の使用がブロックされます。
  6. オリジンのリストに追加されなかったクロスオリジンの iframe(ad.example)では、この機能の使用がブロックされます。これは、iframe タグに allow 属性が含まれている場合も同様です。

Permissions-Policy HTTP レスポンス ヘッダー

ユーザーがリクエストを行うと、サーバーは Permissions Policy ヘッダーで応答し、ブラウザはそのヘッダーに基づいてアクセスを許可します。

Permissions-Policy: &lt;feature&gt;=(&lt;token&gt;|&lt;origin(s)&gt;)

サーバーからのレスポンスの Permissions-Policy ヘッダーを使用して、対象物で許可されるオリジンを設定する。ヘッダー値には、オリジンのトークンと文字列の組み合わせを指定できます。利用可能なトークンは、すべてのオリジンでは *、同一オリジンでは self です。

ヘッダーが複数の対象物に関するものである場合は、各対象物をカンマで区切ります。複数のオリジンを一覧表示する場合は、オリジンのリスト内の各オリジンをスペースで区切ります。クロスオリジン リクエストのオリジンをリストするヘッダーの場合、iframe タグに allow 属性を含める必要があります。

Key-Value ペアの例を次に示します。

  • 構文: [FEATURE]=*
    • すべてのオリジンにポリシーを適用
    • 例: geolocation=*
  • 構文: [FEATURE]=(self)
    • 同一オリジンにポリシーを適用
    • 例: geolocation=(self)
  • 構文: [FEATURE]=(self [ORIGIN(s)])
    • 同じオリジンと指定されたオリジンにポリシーを適用
    • 例: geolocation=(self "https://a.example" "https://b.example")
    • selfhttps://your-site.example の省略形です。
  • 構文: [FEATURE]=([ORIGIN(s)])
    • 同じオリジンと指定されたオリジンにポリシーを適用
    • 例: geolocation=("https://your-site.example" "https://a.example" "https://b.example")
    • この構文を使用する場合、オリジンの 1 つをエンベダーのオリジンにする必要があります。埋め込みページ自体に権限が付与されていない場合、そのページに埋め込まれた iframe は、権限ポリシーによって権限が委任されるため、元のリストに追加されてもブロックされます。self トークンを使用することもできます。
  • 構文: [FEATURE]=()
    • すべてのオリジンで機能がブロックされます
    • 例: geolocation=()

異なるサブドメインとパス

https://your-site.examplehttps://subdomain.your-site.example などの異なるサブドメインは、同一サイトのクロスオリジンとみなされます。そのため、オリジン リストにサブドメインを追加しても、同じサイトの別のサブドメインにアクセスすることはできません。この機能を使用する埋め込みサブドメインはすべて、オリジン リストに個別に追加する必要があります。たとえば、ユーザーの閲覧トピックへのアクセスを同一オリジンへのアクセスがヘッダー Permissions-Policy: browsing-topics=(self) でのみ許可されている場合、同じサイトの別のサブドメイン https://subdomain.your-site.example の iframe はトピックにアクセスできません。

https://your-site.examplehttps://your-site.example/embed のような異なるパスは同一オリジンと見なされ、異なるパスをオリジンリストに含める必要はありません。

iframe の allow 属性

iframe の設定

クロスオリジンで機能を使用する場合、iframe はタグ内に allow 属性を指定して機能にアクセスできるようにする必要があります。

構文: <iframe src="[ORIGIN]" allow="[FEATURE] <'src' | [ORIGIN(s)]"></iframe>

次に例を示します。

<iframe src="https://trusted-site.example" allow="geolocation">

iframe ナビゲーションの処理

iframe ナビゲーションの設定

デフォルトでは、iframe の移動先が別のオリジンの場合、ポリシーはその転送先のオリジンには適用されません。iframe の移動先のオリジンを allow 属性にリストすることで、元の iframe に適用されていた権限ポリシーが、iframe の移動先のオリジンに適用されます。

<iframe src="https://trusted-site.example" allow="geolocation https://trusted-site.example https://trusted-navigated-site.example">

実際の動作は、iframe ナビゲーションのデモでご覧いただけます。

権限ポリシーの設定例

次の設定の例は、デモで確認できます。

すべてのオリジンで許可される機能

対象物へのアクセスが許可されたすべてのオリジンのアーキテクチャ

Permissions-Policy: geolocation=*
<iframe src="https://trusted-site.example" allow="geolocation">
<iframe src="https://ad.example" allow="geolocation">

オリジンのリストが * トークンに設定されている場合、その機能はページ上にあるすべてのオリジン(そのオリジンとすべての iframe を含む)で許可されます。この例では、https://your-site.example から配信されるすべてのコードと、https://trusted-site.example iframe と https://ad.example から配信されるコードから、ユーザーのブラウザの位置情報機能にアクセスできます。なお、許可属性も iframe 自体に設定する必要があり、また、オリジンをヘッダーのオリジン リストに追加する必要があります。

この設定については、デモをご覧ください。

同一オリジンでのみ許可される機能

同一オリジンのみが対象物にアクセスできるアーキテクチャ

Permissions-Policy: geolocation=(self)

self トークンを使用すると、同一オリジンへの位置情報の使用のみが許可されます。クロスオリジンはこの機能にアクセスできません。この例では、https://trusted-site.exampleself)のみが位置情報にアクセスできます。この機能を自分のページのみに必要とし、他の誰にも使用させたくない場合は、この構文を使用します。

この設定については、デモをご覧ください。

同一オリジンと特定のクロスオリジンで許可される機能

対象物へのアクセスを許可されている特定のオリジンのアーキテクチャ

Permissions-Policy: geolocation=(self "https://trusted-site.example")

この構文では、自身(https://your-site.example)と https://trusted-site.example の両方で位置情報を使用できます。iframe タグに allow 属性を明示的に追加してください。<iframe src="https://ad.example" allow="geolocation"> を含む別の iframe がある場合、https://ad.example は位置情報機能にアクセスできません。ユーザーの機能にアクセスできるのは、元のページと、元のページ、および iframe タグに allow 属性が指定されている、元のページと https://trusted-site.example のみです。

この設定については、デモをご覧ください。

すべてのオリジンで機能がブロックされます

すべてのオリジンが機能にアクセスできないアーキテクチャ

Permissions-Policy: geolocation=()

オリジンのリストが空の場合、この機能はすべてのオリジンでブロックされます。この設定については、デモをご覧ください。

JavaScript API を使用する

機能ポリシーの既存の JavaScript API が、ドキュメントまたは要素(document.featurePolicy or element.featurePolicy)のいずれかのオブジェクトとして検出されています。権限ポリシーの JavaScript API はまだ実装されていません。

Feature Policy API は権限ポリシーで設定されたポリシーに使用できますが、いくつかの制限があります。JavaScript API の実装に関して未解決の問題が残っており、そのロジックを Permissions API に移行するための提案がなされています。ディスカッションにご参加ください。

featurePolicy.allowsFeature(feature)

  • この機能がデフォルトのオリジンの使用で許可されている場合、true を返します。
  • 権限ポリシーで設定されたポリシーと以前の機能ポリシーで動作は同じです。
  • allowsFeature() が iframe 要素(iframeEl.featurePolicy.allowsFeature('geolocation'))で呼び出されると、iframe で allow 属性が設定されているかどうかが戻り値に反映されます

featurePolicy.allowsFeature(feature, origin)

  • 指定されたオリジンで対象物が許可されている場合、true を返します。
  • document でこのメソッドが呼び出された場合、機能ポリシーと同様に、このメソッドは指定されたオリジンで対象物が許可されているかどうかを通知しなくなります。このメソッドは、そのオリジンで対象物を許可できる可能性があることを示します。iframe に allow 属性が設定されているかどうかを再度確認する必要があります。デベロッパーは iframe 要素の allow 属性について追加チェックを行い、その機能がサードパーティの配信元で許可されているかどうかを判断する必要があります。

element オブジェクトを使用して iframe 内の機能を確認する

許可属性を考慮しない document.allowsFeature(feature, origin) とは異なり、element.allowsFeature(feature) は使用できます。

const someIframeEl = document.getElementById('some-iframe')
const isCameraFeatureAllowed = someIframeEl.featurePolicy.allowsFeature('camera')

featurePolicy.allowedFeatures()

  • デフォルトのオリジンの使用が許可される機能のリストを返します。
  • 権限ポリシーと機能ポリシーで設定されたどちらのポリシーでも動作は同じです
  • 関連付けられたノードが iframe の場合、許可属性が考慮されます。

featurePolicy.features()

  • ブラウザで使用可能な機能のリストを返します。
  • 権限ポリシーと機能ポリシーで設定されたどちらのポリシーでも動作は同じです

Chrome DevTools の統合

Chrome DevTools と権限ポリシーの統合

DevTools での権限ポリシーの仕組みを確認します。

  1. Chrome DevTools を開きます
  2. [Application] パネルを開いて、各フレームで許可されている機能と許可されていない機能を確認します。
  3. サイドバーで、検査するフレームを選択します。選択したフレームで使用できる機能のリストと、そのフレームでブロックされている機能のリストが表示されます。

Feature-Policy からの移行

現在 Feature-Policy ヘッダーを使用している場合は、次の手順で権限ポリシーに移行できます。

機能ポリシーのヘッダーを権限ポリシーのヘッダーに置き換える

機能ポリシーのヘッダーは Chromium ベースのブラウザでのみサポートされており、Permissions Policy ヘッダーは Chrome 88 以降でサポートされているため、既存のヘッダーを権限ポリシーを使用して更新しても安全です。

古い
Feature-Policy:
  autoplay *;
  geolocation 'self';
  camera 'self' 'https://trusted-site.example';
  fullscreen 'none';

機能ポリシーについて説明します。

新規
Permissions-Policy:
  autoplay=*,
  geolocation=(self),
  camera=(self "https://trusted-site.example"),
  fullscreen=()

権限ポリシーが追加されました。

document.allowsFeature(feature, origin) の使用状況を更新する

document.allowsFeature(feature, origin) メソッドを使用して iframe で許可されている機能を確認する場合は、それを含む document ではなく、iframe 要素にアタッチされた allowsFeature(feature) メソッドを使用します。メソッド element.allowsFeature(feature) では allow 属性が考慮されますが、document.allowsFeature(feature, origin) では考慮されません。

document で機能のアクセス権を確認しています

引き続き document をベースノードとして使用するには、iframe タグの allow 属性をさらに確認する必要があります。

<iframe id="some-iframe" src="https://example.com" allow="camera"></iframe>
Permissions-Policy: camera=(self "https://example.com")
const isCameraPolicySet = document.featurePolicy.allowsFeature('camera', 'https://example.com')

const someIframeEl = document.getElementById('some-iframe')
const hasCameraAttributeValue = someIframeEl.hasAttribute('allow')
&& someIframeEl.getAttribute('allow').includes('camera')

const isCameraFeatureAllowed = isCameraPolicySet && hasCameraAttributeValue

document を使用して既存のコードを更新する代わりに、前の例のように element オブジェクトで allowsFeature() を呼び出すことをおすすめします。

Reporting API

Reporting API はウェブ アプリケーション向けのレポート メカニズムを一貫した形で提供します。また、権限ポリシー違反のための Reporting API は試験運用版の機能としてご利用いただけます。

試験運用版の機能をテストする場合は、チュートリアルに沿って、chrome://flags/#enable-experimental-web-platform-features でフラグを有効にします。このフラグを有効にすると、DevTools の [Application] タブで権限ポリシー違反を確認できます。

次の例は、Reporting API のヘッダーの構成を示しています。

Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default"

Content-Security-Policy: script-src 'self'; object-src 'none'; report-to main-endpoint;
Document-Policy: document-write=?0; report-to=main-endpoint;

現在の実装では、上記の例のように「default」という名前のエンドポイントを構成することで、そのフレーム内で発生した違反からポリシー違反レポートを受け取ることができます。サブフレームには独自のレポート構成が必要です。

補足説明

権限ポリシーについて詳しくは、次のリソースをご覧ください。