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.html
https://aaa.bbb.zzz/ccc.html
は同一オリジンだけど、
https://aaa.bbb.zzz/aaa/bbb.html
http://aaa.bbb.zzz/aaa/bbb.html
http://aaa.bbb.zzz:8080/aaa/bbb.html
https://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
を指定する。
ということをすればよいのだろうかね。。