Access‑Control‑Allow‑Origin ヘッダー 完全ガイド
CORS エラーの原因となる Access‑Control‑Allow‑Origin ヘッダーを完全に理解して解決しましょう。構文、セキュリティ、Nginx/Node.js の設定例まで網羅します。
ウェブ開発をしていると、コンソールに一度は「CORS error」という恐ろしいメッセージを目にしたことがあるでしょう。このエラーはほとんどの場合、別のオリジン(origin)からのリソースを要求するときに発生します。そして、この問題を解決する鍵が「Access‑Control‑Allow‑Origin ヘッダー」にあります。
この記事では、クロスオリジンリソース共有(CORS)の中核である Access‑Control‑Allow‑Origin ヘッダーが何か、どのように動作するか、そして実際のサーバー環境ではどう設定すればよいかを詳しく解説します。この記事を読み終えるころには、CORS エラーに自信を持って対処できるようになっているでしょう!
Access‑Control‑Allow‑Origin とは何ですか?
Access‑Control‑Allow‑Origin は HTTP レスポンスヘッダーの一つです。サーバーがクライアントに「このレスポンスは特定のオリジン(origin)と共有してもよいですよ」ということを知らせる役割を持ちます。
ウェブブラウザはセキュリティの観点から「同一オリジンポリシー(Same‑Origin Policy)」を遵守します。このポリシーは、基本的にスクリプトが自身が読み込まれたオリジンとは異なるオリジンのリソースと相互作用することを禁止します。たとえば、https://my‑awesome‑site.com で実行されるスクリプトは https://api.another‑site.com の API を直接呼び出すことができません。
しかし、現代のウェブアプリケーションでは、複数のサービスの API を呼び出すなど、他のオリジンのリソースを用いることが必須になっています。このとき必要になるのが クロスオリジンリソース共有(Cross‑Origin Resource Sharing, CORS) メカニズムであり、Access‑Control‑Allow‑Origin ヘッダーはこのメカニズムのもっとも基本的で重要な部分です。
CORS の動作仕組みは簡単です。
-
ブラウザが他のオリジンへ HTTP リクエストを送るとき、リクエストヘッダーの
Originフィールドにリクエストを送信するオリジンを含めて送ります。 -
リクエストを受けたサーバーはこのリクエストを許可するかどうかを判断し、レスポンスヘッダーの
Access‑Control‑Allow‑Originフィールドにアクセスを許可するオリジンを明示して応答します。 -
レスポンスを受け取ったブラウザは、自分が送ったリクエストの
Origin値とサーバーが返したAccess‑Control‑Allow‑Originの値を比較します。二つの値が一致すればリソースを正常に読み込み、そうでなければ CORS エラーを発生させ、リソースをブロックします。
文法と使用法
Access‑Control‑Allow‑Origin ヘッダーは次のような三つの主要な値を持つことができます。
Access‑Control‑Allow‑Origin: *
Access‑Control‑Allow‑Origin: <origin>
Access‑Control‑Allow‑Origin: null
それぞれの値がどのような意味を持つか、詳しく見てみましょう。
*(ワイルドカード)
もっとも簡単な設定方法です。* は「すべてのオリジンからのリクエストを許可する」という意味です。どのドメインからでも自分のサーバーのリソースにアクセスできるようになります。
Access‑Control‑Allow‑Origin: *
開発初期段階や公開 API のように、オリジンを問わず誰でもアクセスできるリソースを提供する際に便利です。ただし 認証情報(credentials)が含まれたリクエストには * を使うことはできないという重大な制約があります。クッキーや認証ヘッダーを用いるリクエストに対して * を返すと、ブラウザはセキュリティエラーを発生させます。
<origin>(特定のオリジン)
もっとも安全で推奨される方法です。https://my‑awesome‑site.com のように、リソースアクセスを許可する正確なオリジンを明示します。
Access‑Control‑Allow‑Origin: https://developer.mozilla.org
このように設定すると https://developer.mozilla.org から送られたリクエストに対してのみリソースを共有し、それ以外のすべてのオリジンからのリクエストはブラウザによってブロックされます。ひとつのオリジンしか明示できないため、複数のオリジンを許可する必要がある場合は、サーバー側でリクエストの Origin ヘッダー値をチェックし、許可リストにある値で動的に設定してやる必要があります。
null
null 値は少し特殊なケースで使用されます。例えば、ローカルファイル(file://)からリクエストを送る場合やリダイレクトが発生する場合、Origin ヘッダーの値が null になることがあります。ただしセキュリティ上、null を明示的に許可することは非常に慎重であるべきです。
よくある問題と解決方法
CORS 関連の問題の中でもっとも典型的なのは 認証情報(credentials)が含まれたリクエストが失敗するケースです。
fetch API や XMLHttpRequest を使うときに credentials: 'include' オプションを指定すると、クッキーや認証ヘッダーといった認証情報をリクエストに含めて送ることができます。しかしこの場合、サーバーは次のようなルールを必ず守らねばなりません。
-
Access‑Control‑Allow‑Originヘッダー値としてワイルドカード(*)を使ってはいけません。必ずリクエストを送った特定のオリジンを明示しなければなりません。 -
レスポンスに
Access‑Control‑Allow‑Credentials: trueヘッダーを含めなければなりません。このヘッダーがないと、ブラウザは認証情報を含んだレスポンスを拒否します。
もしサーバーがワイルドカード(*)を使いながら認証を許可しようとすると、ブラウザはこのレスポンスを無効としてエラーを発生させます。したがって認証が必要な API を開発する際には、必ず許可するオリジンを明確に指定することが重要です。
セキュリティ考慮事項
Access‑Control‑Allow‑Origin: * の設定は便利ですが、セキュリティ面では潜在的なリスクを抱えています。この設定は悪意のあるサイトを含むすべてのオリジンがあなたのサーバーのリソースにアクセスできるようになってしまうからです。
例えば、内部でのみ使うべき API を * で設定してしまうと、外部からその API を無断で呼び出して情報を盗んだり、サーバーに負荷をかけたりする可能性があります。
したがって本番環境では次のようなセキュリティのベストプラクティスに従うことが望ましいです。
-
許可リスト(Allowlist)を使う:リソースアクセスを許可すべきオリジンをあらかじめ定義しておき、サーバーはリクエストの
Originヘッダーがこの一覧に含まれている場合にのみ、そのオリジンをAccess‑Control‑Allow‑Originの値として設定して応答します。 -
最小権限の原則:必要なオリジンだけにアクセスを許可し、可能であれば
*の使用は避けましょう。
サーバー設定例
実際のサーバー環境で Access‑Control‑Allow‑Origin ヘッダーをどのように設定するか、Nginx と Node.js(Express)の例を通して見ていきましょう。
Nginx 設定例
Nginx では add_header ディレクティブを使用してヘッダーを簡単に追加できます。
1. すべてのオリジンを許可(非推奨)
# nginx.conf
location / {
add_header 'Access‑Control‑Allow‑Origin' '*';
# …他の設定…
}
2. 特定のオリジンのみを許可(推奨)
# nginx.conf
location / {
add_header 'Access‑Control‑Allow‑Origin' 'https://your‑domain.com';
add_header 'Vary' 'Origin'; # キャッシュ関連の問題を防ぐために追加
# …他の設定…
}
サーバーが特定のオリジンを応答に返すときは、レスポンスが Origin リクエストヘッダーによって変化しうることをクライアントおよび中間キャッシュサーバーに知らせるために Vary: Origin ヘッダーも一緒に返すのが望ましいです。
Node.js(Express)設定例
Express フレームワークではミドルウェアを用いてすべてのレスポンスに CORS ヘッダーを簡単に追加できます。cors といったライブラリを使えば便利ですが、自分で実装する方法は次のとおりです。
1. すべてのオリジンを許可(非推奨)
// app.js
const express = require('express');
const app = express();
app.use((req, res, next) => {
res.setHeader('Access‑Control‑Allow‑Origin', '*');
// 必要な他の CORS ヘッダー(Access‑Control‑Allow‑Methods 等)
next();
});
// …ルート設定…
2. 特定のオリジンのみを許可(推奨)
// app.js
const express = require('express');
const app = express();
const allowedOrigins = ['http://localhost:3000', 'https://your‑domain.com'];
app.use((req, res, next) => {
const origin = req.headers.origin;
if (allowedOrigins.includes(origin)) {
res.setHeader('Access‑Control‑Allow‑Origin', origin);
}
res.setHeader('Access‑Control‑Allow‑Credentials', 'true');
// …必要な他の CORS ヘッダー…
next();
});
// …ルート設定…
より良いウェブの第一歩
CORS の動作原理を正確に理解し、正しく設定することは、安全で効率的なウェブアプリケーションを構築する開発者の基本的な素養と言えるでしょう。今日学んだ内容をもとに、皆さんのプロジェクトで CORS 設定をもう一度見直し、より安全なウェブサービスを作っていってください!