Azure FunctionsのCORSエラー対処法|Web画面からだけ拒否される原因と設定手順

Azure FunctionsのHTTPエンドポイントをcurlやPowerShellなどから呼ぶと成功するのに、Web画面から実行したときだけCORSエラーになる場合は、まずAzure Functions側のCORS許可元を確認します。

ポイントは、CORSで登録するのがAzure FunctionsのURLではなく、Functionsを呼び出しているWebサイト側のオリジンであることです。Azure FunctionsではCORSの許可元が関数アプリ単位で管理されるため、必要なWebサイトのオリジンだけを登録します。認証、Function Key、アクセス権限などとは別の設定として切り分けることが重要です。

この記事では、要求元の確認から現在のCORS設定の確認、許可元の追加、認証エラーとの切り分けまで、Azure CLIを使って順番に整理します。

目次

Azure Functionsをブラウザーから呼ぶとCORSエラーになる理由

Azure Functionsでは、別のWebサイトからHTTPトリガーのエンドポイントへアクセスするためのCORS設定を関数アプリ単位で管理できます。

Microsoft Learnでも、CORSルールはFunction App単位で定義され、アクセスを許可するWebアプリのドメインを個別に登録することが推奨されています。

そのため、次のような状態は矛盾ではありません。

呼び出し方法結果
コマンドからFunctionsへアクセス成功
WebアプリからFunctionsへアクセスCORSエラー
Function Keyなどを付けたWebアクセスCORSエラーのまま

コマンドからHTTPエンドポイントを呼び出せたとしても、それだけではWebサイトのオリジンがCORSで許可されていることを確認したことにはなりません。

特に注意したいのは、CORSと認証を混同しないことです。

Azure FunctionsにはFunction KeyやApp Service Authenticationなど、HTTPエンドポイントを保護する別の仕組みがあります。CORSはそれらの代わりではありません。

最初に確認するのは呼び出し先ではなく要求元のオリジン

CORSを設定するときに最も間違えやすいのが、「どのURLを登録するのか」です。

たとえば、次の構成だったとします。

Webサイト
https://example.com

↓ JavaScriptから呼び出す

Azure Functions
https://sample-function.azurewebsites.net/api/example

CORSの許可元として確認するのは、Functions側の

https://sample-function.azurewebsites.net

ではなく、Webサイト側の

https://example.com

です。

オリジンはスキーム・ホスト・ポートまで確認する

見た目が似ていても、次のようなURLは同じものとして扱わない前提で確認します。

https://example.com
http://example.com
https://www.example.com
https://app.example.com
http://localhost:5173
https://example.com:8443

開発環境では特に、localhostのポート番号を見落としやすくなります。

たとえばWebアプリを

http://localhost:5173

で起動している場合、必要な許可元もこのオリジンです。

Azure CLIのCORSコマンドでも、許可元の例としてポート番号を含む形式が使用されています。

ブラウザーの開発者ツールなどで、実際にWebページを開いているURLを確認してから設定すると間違いが減ります。

Azure Functionsの現在のCORS設定を確認する

要求元が分かったら、すぐに追加するのではなく、最初に現在の設定を確認します。

Azure CLIでは次のコマンドを使用できます。

az functionapp cors show -g RG -n APP

RGにはリソースグループ名、APPにはFunction App名を指定します。

たとえば説明用に次の名前だったとします。

リソースグループ: example-rg
Function App: example-function

この場合は次の形になります。

az functionapp cors show -g example-rg -n example-function

az functionapp cors showは、Function Appに設定されている許可元を確認するためのAzure CLIコマンドです。

ここで確認したいのは、ブラウザーからアクセスしているWebサイトのオリジンが既に登録されているかどうかです。

たとえば要求元が

https://example.com

なら、そのオリジンが許可元に含まれているか確認します。

必要なオリジンだけCORSに追加する

必要なオリジンが登録されていなければ、az functionapp cors addで追加できます。

基本形は次のとおりです。

az functionapp cors add -g RG -n APP --allowed-origins https://example.com

実際にはRGAPPhttps://example.comを自分の環境に置き換えます。

説明用の例では次のようになります。

az functionapp cors add \
  -g example-rg \
  -n example-function \
  --allowed-origins https://example.com

Azure CLIでは--allowed-originsを使って、クロスオリジン要求を許可するオリジンを指定できます。

設定後はもう一度確認しておくと安全です。

az functionapp cors show -g example-rg -n example-function

ここまでできたら、ブラウザーから同じ操作を再実行します。

CORSはFunction App単位なので影響範囲に注意する

Azure FunctionsのCORS設定で重要なのが、関数単位ではなくFunction App単位で設定されることです。

たとえば一つのFunction Appに、

/api/users
/api/orders
/api/report

という複数のHTTPトリガーがある場合、「/api/usersだけのためにCORSを追加した」という感覚で設定しないほうが安全です。

CORSの許可元リストはFunction Appレベルの設定として扱われます。

実務では、

  1. どのWebサイトからアクセスさせるのか
  2. そのFunction AppにはほかにどのHTTPエンドポイントがあるのか
  3. そのオリジンをFunction App全体として許可して問題ないか

まで確認してから追加すると、不要な許可を残しにくくなります。

ワイルドカード「*」で恒久対応しない

Azure CLIでは、許可元として*を指定することもできます。

しかし、Microsoft Learnでは、すべてのサイトを許可するワイルドカードではなく、アクセスを必要とするWebアプリのドメインを個別に登録するよう案内されています。

したがって、本番環境で

*

を恒久的な解決策として設定するのは避けます。

たとえば、

https://example.com

からしか利用しないのであれば、そのオリジンだけを許可します。

開発環境と本番環境の両方が必要なら、それぞれ必要性を確認したうえで登録します。

http://localhost:5173
https://example.com

「CORSエラーが消えればよい」という理由だけで許可範囲を広げないことが重要です。

CORSが直った後に401や403が出る場合は別問題

CORS設定を修正した後、エラーが

401 Unauthorized
403 Forbidden

などに変わることがあります。

この場合は、CORSだけを見るのではなく認証・認可側へ切り分けます。

Azure Functionsでは、HTTPエンドポイントの保護としてFunction KeyやApp Service Authentication/Authorizationなどを利用できます。Microsoft Learnでも、CORSとは別にHTTPエンドポイントのアクセスキーや認証について説明されています。

切り分けの考え方は次のようになります。

状況主に確認する場所
ブラウザーでCORSエラーCORSの許可元
401になる認証情報や認証設定
403になる認可、アクセス制限、アプリ側の拒否条件など
Function Keyが必要HTTPトリガーのアクセスレベルやキー
特定ネットワークからしか接続できないApp Serviceのアクセス制限など

重要なのは、CORSを認証機能として扱わないことです。

CORSで

https://example.com

を許可したからといって、そのWebサイトの利用者本人が認証されたことにはなりません。

反対に、正しいAPIキーや認証情報を持っていても、ブラウザーの要求元がCORSで許可されていなければ、CORS側の問題は別途解決する必要があります。

CORSとアクセス制限も別物として考える

Azure Functionsには、CORS以外にもApp Serviceのアクセス制限などがあります。

Microsoft Learnでは、アクセス制限について、許可・拒否ルールを使ってアプリへのトラフィックを制御する仕組みとして説明しています。

つまり、

CORS

ネットワークやIPなどによるアクセス制御

は目的が異なります。

「CORSを設定したから、許可していないコマンドラインクライアントからAPIを呼べなくなる」と考えるのは適切ではありません。

HTTPエンドポイント自体を保護したい場合は、認証、アクセスキー、ネットワーク制限などを含めて別途設計します。

不要になったCORS許可元を削除する

開発終了後のlocalhostや、廃止したWebサイトのオリジンを残し続ける必要はありません。

不要な許可元はaz functionapp cors removeで削除できます。

az functionapp cors remove \
  -g RG \
  -n APP \
  --allowed-origins https://example.com

説明用の例では次のようになります。

az functionapp cors remove \
  -g example-rg \
  -n example-function \
  --allowed-origins http://localhost:5173

Azure CLIではcors removeによる許可元の削除がサポートされています。

削除後は再度、

az functionapp cors show -g example-rg -n example-function

で確認しておくと確実です。

デプロイスロットを使っている場合は対象を間違えない

Azure Functionsでデプロイスロットを利用している場合は、CORSを変更する対象にも注意します。

az functionapp corsaddshowremoveには--slotオプションがあります。--slotを指定しない場合はProductionスロットが対象になります。

たとえばstagingスロットを確認するなら、次のような形です。

az functionapp cors show \
  -g RG \
  -n APP \
  --slot staging

許可元を追加する場合も同様です。

az functionapp cors add \
  -g RG \
  -n APP \
  --slot staging \
  --allowed-origins https://staging.example.com

ステージング環境でCORSエラーが出ているのにProduction側だけ変更してしまうと、原因が解消しません。

スロットを利用している環境では、CORS設定を変更する前に「今ブラウザーがアクセスしているエンドポイントがどのスロットなのか」を確認します。

Web画面だけCORSで失敗するときの確認順序

原因を素早く絞り込むには、次の順序で確認すると分かりやすくなります。

要求元を確認する

ブラウザーで開いているWebサイトのオリジンを確認します。

https://example.com

開発中なら、ポート番号まで確認します。

http://localhost:5173

現在のCORS設定を確認する

az functionapp cors show -g RG -n APP

スロットを使っている場合は対象スロットも確認します。

必要なオリジンだけ追加する

az functionapp cors add \
  -g RG \
  -n APP \
  --allowed-origins https://example.com

*で広く許可するのではなく、実際に必要な要求元を登録します。

ブラウザーから再実行する

CORSエラーが消えたか確認します。

ここで401や403など別のエラーになった場合は、CORS設定を追加し続けるのではなく、認証・認可・アクセス制御へ調査対象を移します。

不要な許可元を削除する

az functionapp cors remove \
  -g RG \
  -n APP \
  --allowed-origins https://old.example.com

一時的な開発環境や廃止済みサイトのオリジンを残さないようにします。

まとめ

Azure FunctionsのHTTPエンドポイントがコマンドからは呼べるのに、Web画面からだけCORSで拒否される場合は、まずWebサイト側の要求元オリジンとFunction AppのCORS設定を照合します。

確認すべき流れはシンプルです。

  1. ブラウザーの要求元オリジンを確認する
  2. az functionapp cors showで現在の設定を見る
  3. az functionapp cors addで必要なオリジンだけ追加する
  4. ブラウザーから再実行する
  5. 401・403などが残れば認証や権限を別に調べる
  6. 不要な許可元はaz functionapp cors removeで削除する

CORSはFunction App単位で設定され、認証やAPIキー、ネットワークアクセス制御とは役割が異なります。

「コマンドでは成功するからFunctions側は問題ない」と判断するのではなく、要求元 → 現在のCORS設定 → 必要な許可元 → 認証・権限の順番で切り分けると、原因を追いやすくなります。

この記事を書いた人

実務の現場で詰まりがちなポイントを地図にするITブログ「IT trip」を運営。Windows/Office(Teams・Excel)からSQL、サーバ運用、ガジェットまで、再現性のある手順と“なぜそうなるか”を丁寧に解説します。読んだらすぐ試せること、そして迷った人の次の一歩が見えることを大切にしています。

コメント

コメントする

目次