修正:ワイルドカードオリジンと認証情報のエラー

Access-Control-Allow-Credentials: trueとAccess-Control-Allow-Origin: *を使用した場合のよくあるCORSエラーの診断と修正。主要サーバーフレームワークでの解決策を含みます。

Credentials

詳細な説明

問題

ブラウザコンソールにこのエラーが表示されます:

Access to fetch at 'https://api.example.com/data' from origin 'https://app.example.com' has been blocked by CORS policy: The value of the 'Access-Control-Allow-Origin' header in the response must not be the wildcard '*' when the request's credentials mode is 'include'.

サーバーが以下を送信した場合に発生します:

Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true

なぜ失敗するか

CORS仕様(Fetch Standard)はこの組み合わせを明示的に禁止しています。任意のオリジンが認証情報付きリクエストを行えることは深刻なセキュリティホールになり、任意のウェブサイトがセッションCookieを盗む可能性があります。

修正方法

ワイルドカードを正確なリクエストオリジンに置き換えます。サーバーはOriginリクエストヘッダーを読み取り、許可リストで検証した後にエコーバックする必要があります。

Express.jsの修正

const cors = require("cors");

const allowedOrigins = ["https://app.example.com"];

app.use(cors({
  origin: (origin, callback) => {
    if (!origin || allowedOrigins.includes(origin)) {
      callback(null, true);
    } else {
      callback(new Error("Not allowed by CORS"));
    }
  },
  credentials: true,
}));

Nginxの修正

map $http_origin $cors_origin {
    default "";
    "https://app.example.com" "$http_origin";
}

add_header Access-Control-Allow-Origin $cors_origin always;
add_header Access-Control-Allow-Credentials "true" always;
add_header Vary Origin always;

Apacheの修正

SetEnvIf Origin "^https://app\.example\.com$" CORS_ORIGIN=$0
Header always set Access-Control-Allow-Origin "%{CORS_ORIGIN}e" env=CORS_ORIGIN
Header always set Access-Control-Allow-Credentials "true"
Header always set Vary "Origin"

クイックチェックリスト

  • オリジンが*ではない
  • オリジンがOriginリクエストヘッダーと正確に一致(プロトコルとポートを含む)
  • Vary: Originが存在
  • クライアントがcredentials: "include"を設定

ユースケース

開発者がCORSミドルウェアにcredentials: trueを追加しましたが、オリジンを*から特定ドメインに変更するのを忘れました。Postman(CORSを無視)ではすべて動作しますが、ブラウザでは失敗します。

試してみる — CORS Header Builder

フルツールを開く