このガイドを使用して、Access-Control-Allow-Originエラーメッセージに関連する、ブラウザのコンソールウィンドウの一般的な問題を解決します。以下に、エラーメッセージの例を示します。 

  • Failed to load ...No 'Access-Control-Allow-Origin' header
  • Cross-Origin Request Blocked:The Same Origin Policy disallows reading the remote resource ...Reason:CORS header 'Access-Control-Allow-Origin' missing
  • Failed to load ...Response to preflight request doesn't pass access control check:No 'Access-Control-Allow-Origin' header present on the requested resource.Origin ... is therefore not allowed access

この記事では、次のトピックについて説明します。

  • トラブルシューティングに関する質問
  • 次に考えられるステップ

エラーの原因

ブラウザベースのWebアプリケーション(アプリフレームワークのアプリなど)が、外部Webサービスから共有リソースを取得するために、クロスオリジン呼び出しを実行しようとします。これは、CORSリクエスト(オリジン間リソース共有)と呼ばれます。

このようなオリジン間のコールを管理するブラウザベースのCORS標準があります。特定の条件が満たされていない場合に、エラーが発生する可能性があります。

これは、必ずしもバグであるとは限りません。ユーザーのWebアプリケーションとリモートの外部サービスによって意図的に禁止されている可能性があります。

1つのオリジン(www.origin1.com)が別のオリジン(www.origin2.com)を呼び出した場合、これを「オリジン間リクエスト」と呼びます。このリクエストを機能させるには、特定の条件を設定する必要があります。呼び出される外部サービス(www.origin2.com)は、応答としてHTTPヘッダー「Access-Control-Allow-Origin」を返す必要があります。

外部サービスからこのヘッダーが返されなかった場合、ブラウザはCORS仕様に従ってリクエストを停止し、上記のいずれかのエラーメッセージが表示されます。

トラブルシューティングに関する質問

  • 呼び出しの開始点となるURL(オリジン)は何ですか?
    これは時折、エラーメッセージそのものにあります。
  • 呼び出される外部サービスのURLは何ですか?
    コンソールのエラーメッセージ内にあることがあります。
  • 取得される内容とその理由は何ですか?PNGファイルですか?スクリプト、CSS、またはフォントファイルですか?何が正確に取得され、何が使用されていますか?
    これにより、リモートアセットの詳しい用途と、そのアセットが重要である理由について把握することができます。
  • この外部リソースの取得で認証は必要か?
    リダイレクトが必要な場合、応答ヘッダー「Access-Control-Allow-Origin」が返されない可能性があります。この場合、呼び出しが失敗します。リソースのURLを、ブラウザの新しいシークレットタブに直接コピーしてください。この方法は、通常の状況で外部リソースにアクセスできるかどうかをテストする場合に適しています(ただし、Webアプリのコード内でこの方法が機能するという保証はありません)。
  • ブラウザの「ネットワーク」タブに「OPTIONS HTTP」メソッドの呼び出しが表示されているか?
    カスタムリクエストのヘッダー、認証、またはその他の条件がオリジン間リクエスト内に存在する場合、ブラウザは追加のHTTPコールを行います。これは、プリフライトコールともいいます。Webアプリのコードによってこの呼び出しが明示的に作成されることはありません。バックグラウンドで動作するブラウザにより、CORS仕様標準の一部としてこの呼び出しが作成されます。
    このOPTIONS呼び出しが行われたとき、レスポンスが成功するため、リソースに対する実際のHTTP呼び出しが起こるために、特定の値がこの呼び出しの応答に含まれている必要があります。OPTIONS呼び出しが失敗した場合、リソースは取得されず、ブラウザのコンソールにCORSエラーが表示されます。OPTIONS呼び出しが表示された場合は、その呼び出しをメモしてください。また、OPTIONS呼び出しの直前でリダイレクト(ステータス302)呼び出しが発生した場合も、その呼び出しをメモしてください。OPTIONS呼び出しでリダイレクトが発生した場合、その呼び出しは高い確率で失敗します。この場合、リソースを取得するための呼び出しも失敗し、CORSエラーが発生します。
  • どのような場合に外部リソースを取得するのか?
    この外部リソースが最初に取得される理由を確認します。これは、回避策や必要な変更の検討に重要である可能性があります。
  • HARファイルを生成する:
    失敗したコールのスナップショットを取得し、その直前と直後に行われた処理を知ることで、問題をデバッグして、ユーザーが問題を再現できなくなるのを防ぐことができます。リクエストおよびレスポンス内のヘッダーを調べ、OPTIONSコールとリダイレクトを特定することができます。

次に考えられるステップ

  • 誰が外部サーバーを所有していますか?CORS仕様の標準に準拠して「Access-Control-Allow-Origin」ヘッダーを返すようにサーバーを変更できる可能性があります。ただし、サーバーが社内で管理されている場合であっても、この方法ですべてが解決されるわけではありません。ある特定の外部サービスがリソースを共有したくないという理由があるかもしれません。外部サーバーが社内で何かしら管理されていない場合、ユースケースが有効であると仮定して、そのベンダーとやりとりしてみたり、別の回避策を検討してみてください。
  • Zendesk App Frameworkを使用してアプリが作成されているか?client.request()呼び出しを使用して、バックエンドプロキシーバーを使用することができます。このプロキシーバーを使用するには、client.requestでcors:falseを設定します。この設定のデフォルト値は「false」です。プロキシサービスはバックエンドサービスなので、ブラウザベースのCORS仕様に従う必要はなく、オリジン間のコールがプロキシを使用して成功する可能性があります。
    ただし、プロキシサービスですべてが解決するわけではありません。プロキシサービスは、外部サービスからバイナリファイルやバイナリ情報を取得することはサポートしていません。他にアプリ固有の理由があるかもしれませんが、これもまた解決策ではありません。
  • リソースを直接Webアプリに埋め込むことはできますか?リソースを取得するためにオリジン間を移動するのではなく、Webアプリにオリジンを含めることを検討してください。これにより、オリジン間コールが完全に(ローカルリソースであるため)避けられ、CORSのどんな問題も消えてなくなります。ただし、これは必ずしも修正されているわけではありません。外部リソースURLがあらかじめわかっていないか、リソースが大きすぎてローカルリソースに収まらない場合や、リソースが頻繁に変更されてローカルの静的リソースとしてダウンロードされない場合があります。
  • ブラウザのバージョンは何ですか?CORS仕様が標準であるにもかかわらず、ブラウザに表示されるメッセージが異なる場合があります。ChromeとFirefoxでは、異なるコンソールメッセージが表示されます。
  • 修正できない場合があります。外部サービスからのリソースリクエストは、ブラウザWebアプリのコンテキストで共有されることを意図しない場合があります。リソース所有者が、リソースを共有するかどうかを判断します。これは、Webアプリの問題ではありません。仕様に従ってこうなっている場合がります。

詳細については、以下の記事を参照してください。

  • Wikipediaの記事:クロスオリジンリソース共有
  • Web.Devの記事:クロスオリジンリソース共有(CORS)
  • Mozillaの記事:クロスオリジンリソース共有(CORS)
  • Mozillaの記事: OPTIONS
  • Fetchの記事:Fetch
  • Fetchの記事:CORSプロトコル
Powered by Zendesk