はじめに
以下記事の作業をしていた際に掲題のエラーが出て解決に時間がかかったので備忘です
※以下記事を書き終わってから本記事を書くために再現しようと思ったらなぜか再現できなかったので、覚えている範囲で書きます
事象
ブラウザのコンソールで以下エラーが発生する
Navigation to external protocol blocked by sandbox, because it doesn't contain any of: 'allow-top-navigation-to-custom-protocols', 'allow-top-navigation-by-user-activation', 'allow-top-navigation', or 'allow-popups'
調査
調べたところ、iframeでsandbox
が指定されている場合に外部プロトコルへ移動しようとした際にエラーとなるようです。
ただ、なぜか記事投稿後の今は発生しない...
iframe自体はkeycloak-js
のkeycloak.js
内で追加されており、開発者ツールで見てもsandboxが指定されたiframeが追加されているのでなぜ発生しないのかが分かっていません。
(分かる人いたら教えて頂けるとありがたいです)
...
function check3pCookiesSupported() {
var promise = createPromise();
if (loginIframe.enable || kc.silentCheckSsoRedirectUri) {
var iframe = document.createElement('iframe');
iframe.setAttribute('src', kc.endpoints.thirdPartyCookiesIframe());
iframe.setAttribute('sandbox', 'allow-scripts allow-same-origin'); // ここで設定して
iframe.setAttribute('title', 'keycloak-3p-check-iframe' );
iframe.style.display = 'none';
document.body.appendChild(iframe); // ここで追加している
...
暫定対応
もし仮に同じ状況になった人のために書いておくと、上記にも書いてありますがiframeを追加する前の条件分岐が以下となっています。
if (loginIframe.enable || kc.silentCheckSsoRedirectUri)
なので、上記どちらもfalseになるようにすれば良いです。
これらはコードを追っていくと明示的にfalseにできそうな箇所がありました。
...
kc.init = function (initOptions) {
console.log('hogehhoge')
if (kc.didInitialize) {
throw new Error("A 'Keycloak' instance can only be initialized once.");
}
kc.didInitialize = true;
...中略
if (initOptions) {
...中略
if (typeof initOptions.checkLoginIframe !== 'undefined') {
loginIframe.enable = initOptions.checkLoginIframe; // ここと
}
...中略
if (initOptions.silentCheckSsoRedirectUri) {
kc.silentCheckSsoRedirectUri = initOptions.silentCheckSsoRedirectUri; // ここ
}
...
というわけで、keycloak.init()
の引数のオブジェクトにcheckLoginIframe: false
を追加し、silentCheckSsoRedirectUri
は指定しなければ良さそうです。
エラーが発生していた当時は上記対応でエラーが出なくなりました。
ただ、今はcheckLoginIframe: false
を追加しなくてもエラーが出ないため、あくまで暫定対応でしかないと思います。
おわりに
なんとも気持ち悪い状態ですが、原因が分からずに直っている状態です。
エラーが出た当時は記事に記載しているソースとは結構違っており、おそらく何か悪い実装をしていた結果発生した事象なのかなと思います。
もし何か分かれば or 指摘があれば記事追記します。