修正:ワイルドカードオリジンと認証情報のエラー
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を無視)ではすべて動作しますが、ブラウザでは失敗します。