埋め込みゲームでログインできないのはなぜ?別タブで開く理由
遊びを届ける執筆にClaudeを使用しています。

アソバースでゲームを開いたのに真っ白な画面が出た、またはログインボタンを押したら Google のエラー画面になった——そういう経験をした人がいるかもしれません。これは不具合ではなく、ブラウザーの仕様と Google のポリシーが組み合わさった結果です。埋め込みが拒否される条件と、ログインが失敗する条件は、それぞれ別の仕組みに由来しています。この記事では、ふたつの原因を分けて説明し、アソバースがなぜ「別タブで開く」という対処を選んでいるのかを整理します。
この記事の目次
ふたつの原因:表示の問題とログインの問題
外部サイトのゲームをアソバース内の iframe(埋め込み枠)で表示しようとするとき、失敗には大きくふたつの種類があります。
- 表示の失敗:ゲームサイトが「自分のオリジンからしか埋め込みを許可しない」という設定になっており、アソバースの iframe 内でそもそも画面が描画されない。
- ログインの失敗:ゲームは表示できても、iframe 内でポップアップ認証を起動すると Google の 403 画面になる。Google の OAuth ポリシーが、開発者管理の埋め込みユーザーエージェントへの認可リクエストを禁じているため。
どちらも、ゲームの中身を変えずに iframe の権限を増やすだけでは解決しません。それぞれの原因を理解した上で、作者と利用者が取れる対処が変わってきます。
画面が表示されない:埋め込み禁止ヘッダーの仕組み
ゲームサイトが HTTP レスポンスヘッダーに X-Frame-Options: SAMEORIGIN を付けていると、そのサイトと異なるオリジンからの iframe 読み込みはブラウザーによって拒否されます。アソバース(aso-verse.com)からゲームサイト(例:example.web.app)を埋め込もうとすれば、オリジンが一致しないため画面は描画されません。アソバースで確認済みの事例では、あるゲームサイトの公開レスポンスにこのヘッダーが設定されており、iframe 表示が拒否されることが確認されています。
より新しい方法として、Content Security Policy(CSP)の frame-ancestors ディレクティブも同じ制御を行います。frame-ancestors 'self' と設定されていれば、同一オリジンからの埋め込みだけが許可され、外部プラットフォームからの iframe は受け付けられません。
X-Frame-Options は HTTP レスポンスヘッダーとして送信しなければ効果がありません。HTML の <meta> タグに書いても無効です(MDN Web Docs の仕様記述による)。また ALLOW-FROM 指定は現代のブラウザーでは無視されるため、特定オリジンを許可するには CSP の frame-ancestors を使います。
この制限はゲームサイト側が意図的に設定しているものであり、アソバース側のサンドボックス設定を変更しても回避できません。外部ゲームの iframe に allow-same-origin を追加するといった操作でも、ゲームサイト自身が許可していない限り拒否は続きます。
ログインが通らない:iframe 内の Google OAuth 制限
iframe 内での表示自体は成功していても、ログインボタンを押した瞬間に Google の 403 画面が出ることがあります。これは Google の OAuth 2.0 ポリシーに由来しています。
Google のポリシーは、開発者が管理する埋め込みユーザーエージェント(開発者が任意のスクリプトを挿入できる iframe など)への OAuth 認可リクエストを禁じています。これはユーザーが Google の認証画面に接続していることを確認できる環境を保証するためです。
あるゲームサイトの実装では、Firebase Authentication の signInWithPopup がポップアップを開けない場合(ユーザーによる閉鎖を除く)に signInWithRedirect へ進む実装になっていました。しかし iframe 内からのリダイレクト遷移でも、Google の認可は拒否されます。このフォールバックは開発者がそのゲームに実装したものであり、Firebase が自動的に切り替える標準動作ではありません。
アソバースの確認では、このゲームサイトを埋め込みのまま表示してログインを押すと Google の 403 画面への遷移が再現されました。
403 画面の表示だけからは、Google 側の詳細な拒否理由(アカウント権限の問題か、ポリシー違反かなど)を特定することはできません。少なくとも「埋め込み経路での認証遷移が失敗している」という事実のみが観測できます。
エラーメッセージが出ない理由:iframe の load と error の動作
埋め込み失敗のもうひとつの特徴として、「なぜエラーメッセージも出ないのにゲームが映らないのか」という疑問があります。これにはブラウザーのセキュリティ仕様が関係しています。
MDN Web Docs の仕様記述によれば、ブラウザーは iframe 要素に対して error イベントを発火しません。その代わりに load イベントは、読み込みが失敗した場合でも常に発火します。これはローカルネットワーク内の HTTP サーバーの URL を探索するといった悪用を防ぐためです。
この仕様上の制約から、プラットフォーム側は「load イベントが呼ばれた」という事実を「ゲームが表示できた」という判定に使えません。X-Frame-Options で拒否されても load イベントは届きます。また親ページは別オリジンの iframe の中身やログイン状態を読み取れないため、タイムアウトで失敗を判定する方式も、遅い通信環境での誤判定を招きます。
アソバースの対処:別タブ起動とその範囲
上記の理由から、アソバースでは埋め込みで問題が確認された外部ゲームについて、iframe ではなく作者のサイトを別タブで開く対応を取っています。既存の /play/:id のリンクにアクセスした場合も、壊れた iframe を出さずに作品のカバーと別タブ起動リンクを表示します。
別タブで開くリンクは通常の <a target="_blank" rel="noopener noreferrer"> です。アソバースのアカウント情報(UID・トークン・ログイン状態)は URL に付与せず、opener 接続も確立しません。別タブで開いた後のログインやセーブはゲームサイト側に属し、アソバースへのサインインとは独立しています。
互換性を確認していない外部ゲームは引き続き埋め込みで表示し、プレイヤー画面の上部に「作者のサイトで開く」リンクを常設しています。これにより、表示やゲーム内ログインに問題がある場合の代替手段を提供しています。
アソバースの SDK ブリッジ(Asoverse.ready() / save() など)は、アソバース内に埋め込まれたゲームが作者側で組み込んだ場合にのみ機能します。これはアソバースのゲーム専用 UUID とセーブデータを渡す仕組みであり、外部サイトへのシングルサインオンではありません。Firebase UID・パスワード・メールアドレスはゲームに渡しません。
作者向け:埋め込みを許可する設定と確認の手順
自分のゲームサイトをアソバース内で埋め込み表示したい場合は、以下の点を確認してください。ゲームのホスティング環境によって設定方法が異なりますが、変更の方針は共通です。
埋め込みを許可する HTTP ヘッダーの設定
- レスポンスヘッダーに X-Frame-Options が設定されている場合は削除するか、CSP の frame-ancestors で置き換えます。
- CSP で frame-ancestors を使い、アソバースのオリジン(https://aso-verse.com など)を許可リストに追加します。例:
- 設定後、ブラウザーの開発者ツール(Network タブ)でレスポンスヘッダーを確認し、意図した値が返っているか検証します。
Content-Security-Policy: frame-ancestors 'self' https://aso-verse.com https://asoverse-f8998.web.app;上記は設定の例であり、実際に動作することを保証するものではありません。ホスティングサービスの仕様に従って設定し、本番環境で必ず確認してください。Firebase Hosting の場合は firebase.json の headers セクションで指定できます。
Google ログインを使っている場合の注意
Google OAuth を使ったログインが必要なゲームは、埋め込み内での認証遷移が Google のポリシーによって拒否されます。埋め込みを許可するヘッダーを設定しても、この制限は残ります。この場合、ゲーム側でログインを要求する前に別タブで開くよう案内するか、アソバースに別タブ起動として登録する方法が現実的です。埋め込みヘッダーを緩めるだけでは、ログイン問題は解決しないという点を設計の前提にしてください。
設定変更後の再確認
ゲームサイト側でヘッダー設定や認証フローを変更した場合は、本番オリジンからゲームと認証をそれぞれ確認してください。「ゲームが埋め込み表示できた」「ログイン画面に到達した」「ログインが完了した」「セーブが同期した」は、それぞれ独立した確認項目です。いずれかひとつが確認できても、他の項目を済ませたことにはなりません。


