Access-Control-Allow-Credentials の徹底解説と実践ガイド — CORSでの認証情報管理とセキュリティ対策

はじめに:Access-Control-Allow-Credentialsとは何か

Access-Control-Allow-Credentialsは、クロスオリジンリクエスト(CORS)において、ブラウザがリクエストに含まれる認証情報(Cookie、HTTP認証情報、クライアント証明書など)をクロスオリジンのレスポンスとともに扱うことを許可するためのレスポンスヘッダーです。値は文字列の'true'のみが有効で、これを付与したレスポンスを受け取ったブラウザは、必要に応じてクライアント側のスクリプトからレスポンスへアクセスできるようにします。

CORSの基本とこのヘッダーの位置づけ

CORSは同一生成元ポリシー(Same-Origin Policy)の制約を緩和するためのブラウザ側の仕組みです。ブラウザは、クロスオリジンの要求をサーバーへ送る際にOriginヘッダーを付与し、サーバーはそれに応じてAccess-Control-Allow-Originなどのレスポンスヘッダーで許可を与えます。Access-Control-Allow-Credentialsはこの許可のうち「認証情報を含めて良いか」を示すフラグです。

重要ルール:ワイルドカード禁止と明示的オリジン

仕様上、Access-Control-Allow-Credentialsが'true'の場合、Access-Control-Allow-Originにワイルドカード('*')を指定してはいけません。ブラウザはワイルドカードとクレデンシャル許可の組合せを無効と見なし、クライアント側のスクリプトからレスポンスを利用できなくします。そのため、クレデンシャルを許可する場合は、レスポンスのAccess-Control-Allow-Originに明示的なオリジン(例えば'https://example.com')を返す必要があります。多くの実装では、リクエストのOriginヘッダーを検証し、許可リストにあればそのOriginをそのまま返す動的なエコーを行います。

クライアント側の設定:fetchとXHRの違い

ブラウザ側で認証情報を送信・受信するためには、単にサーバーがAccess-Control-Allow-Credentialsを返すだけでなく、クライアント側のAPI呼び出しで明示的に認証情報の送信を許可する必要があります。

  • fetch API: オプション'credentials'を'same-origin'(デフォルト)や'include'に設定します。クロスオリジンに対してクッキーを送るには'include'を使います。'same-origin'は同一オリジンに対してのみ送信します。
  • XMLHttpRequest: オブジェクトに対してxhr.withCredentials = trueを設定します。

ポイントは、サーバー側のAllow-Credentialsとクライアント側のcredentials/withCredentialsの両方が揃って初めて認証情報が実際にやり取りされることです。

プリフライトとシンプルリクエスト

認証情報の扱い自体はプリフライト(OPTIONS)判定に直接影響しません。しかし、送信したいリクエストの内容(カスタムヘッダーやContent-Typeなど)によってはブラウザがプリフライトを行うため、サーバーはプリフライトリクエストに対しAccess-Control-Allow-Methods、Access-Control-Allow-Headers、必要ならAccess-Control-Max-Ageを返さなければなりません。プリフライトレスポンスにもAccess-Control-Allow-Credentialsを含めることが一般的です。

典型的なサーバー側設定例

以下は実務でよく使われる設定例の概念です。実装の際はフレームワークや環境に応じて細部を調整してください。

  • Node.js/Express(手動): レスポンスに'Access-Control-Allow-Origin'をリクエストのOriginに応じてセットし、'Access-Control-Allow-Credentials'を'true'に設定する。CORSミドルウェア(npmパッケージ'cors')を使う場合はオプション{origin: true, credentials: true}などで動的オリジン対応ができる。
  • Nginx: add_header 'Access-Control-Allow-Credentials' 'true'; とし、Access-Control-Allow-Originは返す前に検証したOriginを返すか、マップで動的に設定する。注意: add_headerは条件ごとに挙動が異なるため設定位置に注意。
  • Apache: Header set 'Access-Control-Allow-Credentials' 'true' を使用、Originのチェックはアプリケーションかmod_rewrite等で行う。
  • Spring Boot: CorsConfigurationでsetAllowCredentials(true)を設定し、allowedOriginsに明示的オリジンを指定する。allowedOriginsに'*'を設定すると例外や警告になるので避ける。

セキュリティ上の注意点

Access-Control-Allow-Credentialsを有効にすることは利便性を高めますが、同時にリスクも伴います。主なリスクと対策は次の通りです。

  • CSRF(クロスサイトリクエストフォージェリ): 認証情報を自動送信することで、悪意あるサイトがユーザーのブラウザを介して認証済みのリクエストを送る可能性があります。対策としてはSameSite属性を利用したクッキー制御、CSRFトークンの導入、Referer/Originチェックなどを併用します。
  • 許可するオリジンの管理: ワイルドカード禁止に加え、信頼できるオリジンのホワイトリストを厳格に管理し、リクエストOriginを検証してからレスポンスにそのOriginを返す実装を採用します。
  • キャッシュの注意: CDNやプロキシでレスポンスがキャッシュされると、異なるOriginに対して間違ったAccess-Control-Allow-Originが返される恐れがあります。Vary: Origin ヘッダーを設定してキャッシュの粒度をOriginごとに分けることが重要です。

よくある誤解と落とし穴

いくつかの典型的な誤解を整理します。

  • "Access-Control-Allow-Credentials='true'を返せば誰でもクッキーが送られる" → クライアント側でcredentials/withCredentialsの設定が必要です。サーバー設定だけでは不十分です。
  • "Access-Control-Allow-Credentialsはサーバー間通信に影響する" → これはブラウザの機能です。サーバー間のHTTP通信(curlやサーバーサイドのHTTPクライアント)には影響しません。
  • "ワイルドカードを併用できる" → 仕様では無効とされています。ブラウザはこの組合せを拒否します。

デバッグのポイント

問題が起きたときは以下を確認します。ネットワークタブでリクエストのOrigin、レスポンスヘッダー(Access-Control-Allow-Origin、Access-Control-Allow-Credentials、Varyなど)、プリフライト(OPTIONS)のレスポンス内容、そしてクライアント側のfetch/xhrのcredentials設定です。ブラウザのコンソールに表示されるCORSエラーは比較的具体的なので、それを手がかりにしてください。またサーバーログでプリフライトが到達しているかどうかも確認します。

実運用チェックリスト

Access-Control-Allow-Credentialsを使う際の最低限のチェックリストです。

  • リクエストOriginを検証し、ホワイトリストにある場合のみそのOriginをAccess-Control-Allow-Originに返す実装になっているか。
  • Access-Control-Allow-Credentialsを'true'に設定しているか。
  • Vary: Originを設定しているか(キャッシュ対策)。
  • クッキーにSecure、HttpOnly、可能ならSameSite属性が適切に設定されているか。
  • CSRF対策(トークン、Origin/Refererチェックなど)が実装されているか。
  • クライアント側でfetch/xhrのcredentials/withCredentialsを正しく設定しているか。

まとめ

Access-Control-Allow-CredentialsはCORS環境で認証情報を安全に扱うための重要なオプションです。しかし、仕様上の制約(ワイルドカード禁止)やキャッシュ、CSRFといったセキュリティリスクを理解していないと、思わぬ脆弱性や通信エラーを招きます。実装ではサーバー側でOriginの検証と動的なレスポンス設定、Varyヘッダーの追加、そしてクッキーの属性やCSRF対策を併せて行うことが重要です。クライアント側でもfetch/xhrの設定を忘れないようにしてください。

参考文献

MDN Web Docs: Access-Control-Allow-Credentials

MDN Web Docs: Cross-Origin Resource Sharing (CORS)

WHATWG Fetch Standard

OWASP: CORS Security Considerations

Express: CORS middleware documentation

Nginx: add_header — Documentation