AMPページにおけるエラー
このブログのAMPページの<amp-iframe>で、下記のエラーが出て困っていた。
Origin of <amp-iframe> must not be equal to container
<amp-iframe>のオリジンはコンテナと同じであってはいけません。
sandbox属性にはallow-same-origin属性は入れているのだが。なぜだろうか。エラーの続きには以下のメッセージが続いていた。なぜかメッセージ的には分割して表示されてしまっているのだが。
if allow-same-origin is set.See https://github.com/ampproject/amphtml/blob/master/spec/amp-iframe-origin-policy.md for details.
合わせるとこういうことか。
Origin of <amp-iframe> must not be equal to container if allow-same-origin is set.See https://github.com/ampproject/amphtml/blob/master/spec/amp-iframe-origin-policy.md for details.
もしallow-same-originをセットしているのなら、<amp-iframe>のオリジンはコンテナと同じであってはいけません。詳細はhttps://github.com/ampproject/amphtml/blob/master/spec/amp-iframe-origin-policy.md を参照すること。
「同じオリジンのiframe srcを許して」いるのに同じオリジンであってはいけないとはどういうことか。しかしそもそもオリジンって何だ?
Origin(オリジン)とは
オリジンは以下で定義される。
なので、同一のオリジンとは
となる。つまり
https://aaa.bbb.zzz/aaa/bbb.htmlhttps://aaa.bbb.zzz/ccc.html
は同一オリジンだけど、
https://aaa.bbb.zzz/aaa/bbb.htmlhttp://aaa.bbb.zzz/aaa/bbb.htmlhttp://aaa.bbb.zzz:8080/aaa/bbb.htmlhttps://ddd.bbb.zzz/ccc.html
はすべて異なるオリジンということになる。
異なるオリジンのページへのスクリプトアクセス
異なるオリジンのページ同士はスクリプトアクセスが制限される。具体的にはwindow・Locationのメソッド・プロパティに制約を受ける。
引用:MDN
Window
| 使用できるメソッド |
|---|
window.blur |
window.close |
window.focus |
window.postMessage |
| 使える属性 | 読み取り・書き込み |
|---|---|
window.closed |
読み取りのみ |
window.frames |
読み取りのみ |
window.length |
読み取りのみ |
window.location |
読み取り/書き込み |
window.opener |
読み取りのみ |
window.parent |
読み取りのみ |
window.self |
読み取りのみ |
window.top |
読み取りのみ |
window.window |
読み取りのみ |
Location
| 使えるメソッド |
|---|
location.replace |
| 属性 | 読み取り・書き込み |
|---|---|
location.href |
書き込みのみ |
上記以外のwindow,locationのメソッド・属性は使用できないということか。
<iframe>のsandbox属性とallow-same-origin
「sandbox属性 - iframe 要素 - HTML | MDN」を読むと、私はsandbox属性に関して何もわかっていないことが分かった。
sandboxは空文字指定で最大の制約がかかる。指定がないと制約がかからない。- 以下のトークンを文字列にスペース区切りで含めることにより、指定した制約が解除される。
allow-forms: 埋め込みのブラウジングコンテキストにフォームの実行を許可allow-modals: 埋め込みのブラウジングコンテキストがモーダルウィンドウを開くことを許可allow-orientation-lock: 埋め込みのブラウジングコンテキストが、スクリーンの向きをロックする機能を無効化することを許可allow-pointer-lock: 埋め込みのブラウジングコンテキストに、Pointer Lock API の使用を許可allow-popups: (window.open、target="_blank"、showModalDialogのような) ポップアップを許可allow-popups-to-escape-sandbox: サンドボックス化したドキュメントが、サンドボックスフラグを強制されない新たなウィンドウを開くことを許可allow-presentation: iframeがpresentationセッションを開始できるようにするかを、埋め込み者が制御することを許可allow-same-origin: コンテンツが同一オリジンを持つとみなす。allow-scripts: 埋め込みのブラウジングコンテキストにスクリプトの実行を許可(ただしポップアップウィンドウは不可)allow-top-navigation: 埋め込みのブラウジングコンテキストがトップレベルのブラウジングコンテキストのコンテンツを操作(読み込み)することを許可allow-top-navigation-by-user-activation: ユーザーの操作に限り、埋め込まれたブラウジングコンテキストがトップレベルのブラウジングコンテキストのコンテンツを操作 (読み込み) することを許可
一番の誤解は、allow-same-originトークンが同一オリジンのiframeを許すのではなくて、別オリジンのiframe srcを同じオリジンだとみなすという部分。
考えてみると同一オリジンのiframe srcが読み込めないはずないもんね。。
あとMDNには以下のことが書いてあった。
- 同一オリジンの場合は
allow-scriptsとallow-same-originの同時利用は避けることを推奨。sandboxを指定しないのと同様の危険性がある。
Iframe origin policy
allow-same-originを誤解していたことがわかり、sandboxが理解できたところで、エラーメッセージのURLのドキュメントを見ると、わりと理解できたような気がしたが、今いち自信がないね。。。
AMPはAMPプロキシでキャッシュされるので、必ずオリジンのホストからページが供給されるとは限らない。なのでもし<amp-iframe>内のページのJSがホストしているページが同じオリジンであることを前提に作られていると、AMPプロキシでキャッシュされた場合不具合が起こる可能性がある。例えば(クロスiframeアクセス)を使用しているものを考える。AMPページはキャッシュされ、別オリジンで提供され、<amp-iframe>内のページはキャッシュされない(ユーザーJSが動いている時点でAMPの要件を満たさないからかな・・)可能性がある。その場合別オリジンとなってホストページ<->iframeアクセスに制限がかかり不具合が発生する可能性がある。
AMPは上記不具合を回避するため、「sandbox属性でallow-same-originを指定した場合は<amp-iframe>のsrcは別オリジンでなければならない」ルールを定めている。<amp-iframe>のコードは別オリジンを前提とすることを強制させるのである。同一オリジンの場合「Origin of <amp-iframe> must not be equal to container」エラーが発生する。 さらにホストページに対してはpostMessageのみ利用可能な制限がかかる。
このルールはsandobox属性でallow-same-originを指定しない場合は適用されない。が別オリジンの場合のiframe制約がかかる。
そうするとあれだな、
<amp-iframe>のsrcがホストページと同じオリジンならallow-same-originは指定しない。<amp-iframe>のsrcがホストページと異なるオリジンで、同じオリジンとみなしたいのであればallow-same-originを指定する。
ということをすればよいのだろうかね。。