MeWrite Docs

CORS with Credentials Error

credentials付きリクエストでCORSポリシー違反が発生するエラー

概要

CORS with Credentials Error は、credentials: 'include' を指定したクロスオリジンリクエストで、サーバーが Access-Control-Allow-Origin: *(ワイルドカード)を返した場合に発生するエラーです。ブラウザのセキュリティ仕様により、認証情報を含むリクエストではワイルドカードオリジンが許可されません。

エラーメッセージ

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 to XMLHttpRequest at 'https://api.example.com/data' from origin 'https://app.example.com'
has been blocked by CORS policy: Response to preflight request doesn't pass access control check:
The value of the 'Access-Control-Allow-Credentials' header in the response is '' which must be 'true'.

原因

  1. ワイルドカードOriginとcredentialsの組み合わせ: Access-Control-Allow-Origin: *credentials: include は共存不可
  2. Access-Control-Allow-Credentials ヘッダーの欠落: サーバーが true を返していない
  3. Access-Control-Allow-Headers のワイルドカード: credentials モードではヘッダーのワイルドカードも不可
  4. プリフライトリクエストの設定不備: OPTIONS リクエストに対する応答が不適切

解決策

1. Express.js(cors ミドルウェア)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
const cors = require('cors');

// NG: ワイルドカードと credentials は共存不可
app.use(cors({
  origin: '*',           // NG
  credentials: true
}));

// OK: 特定のオリジンを指定
app.use(cors({
  origin: 'https://app.example.com',
  credentials: true
}));

// OK: 複数オリジンを動的に許可
const allowedOrigins = [
  'https://app.example.com',
  'https://staging.example.com',
  'http://localhost:3000'
];

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

2. Nginx

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
server {
    location /api/ {
        # NG: ワイルドカード
        # add_header Access-Control-Allow-Origin *;

        # OK: 動的にオリジンを設定
        set $cors_origin "";
        if ($http_origin ~* "^https://(app|staging)\.example\.com$") {
            set $cors_origin $http_origin;
        }

        add_header Access-Control-Allow-Origin $cors_origin always;
        add_header Access-Control-Allow-Credentials true always;
        add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS" always;
        add_header Access-Control-Allow-Headers "Authorization, Content-Type" always;

        # プリフライトリクエスト
        if ($request_method = OPTIONS) {
            add_header Access-Control-Allow-Origin $cors_origin;
            add_header Access-Control-Allow-Credentials true;
            add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
            add_header Access-Control-Allow-Headers "Authorization, Content-Type";
            add_header Access-Control-Max-Age 86400;
            return 204;
        }
    }
}

3. Django(django-cors-headers)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
# settings.py
INSTALLED_APPS = [
    'corsheaders',
    # ...
]

MIDDLEWARE = [
    'corsheaders.middleware.CorsMiddleware',  # 最上位に配置
    # ...
]

# NG: ワイルドカード + credentials
# CORS_ALLOW_ALL_ORIGINS = True
# CORS_ALLOW_CREDENTIALS = True

# OK: 特定オリジンを指定
CORS_ALLOWED_ORIGINS = [
    'https://app.example.com',
    'https://staging.example.com',
]
CORS_ALLOW_CREDENTIALS = True

4. Spring Boot

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
@Configuration
public class CorsConfig implements WebMvcConfigurer {
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/api/**")
            .allowedOrigins("https://app.example.com")  // * は不可
            .allowedMethods("GET", "POST", "PUT", "DELETE")
            .allowedHeaders("Authorization", "Content-Type")
            .allowCredentials(true);  // credentials 許可
    }
}

5. フロントエンド側の設定

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// fetch
const response = await fetch('https://api.example.com/data', {
  method: 'GET',
  credentials: 'include', // Cookie を送信
  headers: {
    'Content-Type': 'application/json'
  }
});

// axios
const api = axios.create({
  baseURL: 'https://api.example.com',
  withCredentials: true // Cookie を送信
});

関連エラー

Browser の他のエラー

最終更新: 2026-02-03