Azure Front Door と Azure App Serivce のCORS設定方法を確認してみた

2022.05.06

いわさです。

昨今はWeb開発の様々なシーンでCORSを意識する必要があると思います。
先日Static Web AppsからバックエンドのFront DoorやApp ServiceのリソースをFetchした際に、CORSエラーが発生しました。

Front DoorでもCORS対応出来ますし、App Serviceで対応することも出来ます。
それぞれの設定方法を整理してみました。

フロントエンド

Staic Web Appsでホスティングする、サンプルのフロントエンドを用意します。

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Hoge</title>
</head>
<body>
    <input type="button" value="FrontDoor0" onclick="fetch('https://hoge0505fd.azurefd.net/image1.png');" />
    <input type="button" value="AppService0" onclick="fetch('https://hoge0505app.azurewebsites.net/image1.png');" />
    <input type="button" value="FrontDoor1" onclick="hoge('https://hoge0505fd.azurefd.net/image1.png');" />
    <input type="button" value="AppService1" onclick="hoge('https://hoge0505app.azurewebsites.net/image1.png');" />
    
    <script type="text/javascript">
        function hoge(url)
        {
            const myHeaders = new Headers();
            myHeaders.append('Content-Type', 'image/png');
            const myInit = {
                method: 'GET',
                headers: myHeaders,
                mode: 'cors',
                cache: 'default'
            };
            fetch(url, myInit)
        }
    </script>
</body>
</html>

hoge0505fd.azurefd.netがFront Doorで、hoge0505app.azurewebsites.netはApp Serviceです。
作りがかなり雑ですが直接fetchさせるパターンと、Preflightを発生させるためにContent-Typeを設定するパターンと用意しました。

なお、プリフライトリクエストの発生方法は以下を参考にさせて頂きました。
CORS の プリフライト・リクエストを発生させて観察する – ラボラジアン

デプロイ時のデフォルトドメインはlively-river-022892310.1.azurestaticapps.netでした。

Azure App Serviceでの設定

検証内ではApp ServiceはLinux PHP7.4の組み込みイメージを使っています。
App ServiceのCORS設定はとても簡単で、CORSメニューで許可するドメインを設定するだけです。(以下の画像だとAccess-Control-Allow-Credentialsを有効化していますが、この検証内では不要です)

こちらでドメインを許可するだけで、対象リクエストのOriginヘッダーを元にAccess-Control-Allow-Origin ヘッダーを追加してくれます。

許可されたオリジン

$ curl -I -H "Origin:https://lively-river-022892310.1.azurestaticapps.net" https://hoge0505.azurewebsites.net/image1.png
HTTP/1.1 200 OK
Content-Length: 109213
Content-Type: image/png
Last-Modified: Thu, 05 May 2022 00:06:47 GMT
Accept-Ranges: bytes
ETag: "1aa9d-5de388491448c"
Server: Apache
Access-Control-Allow-Origin: https://lively-river-022892310.1.azurestaticapps.net
Date: Thu, 05 May 2022 01:34:24 GMT

許可されてないオリジン

$ curl -I -H "Origin:https://lively-river-022892310.2.azurestaticapps.net" https://hoge0505.azurewebsites.net/image1.png
HTTP/1.1 200 OK
Content-Length: 109213
Content-Type: image/png
Last-Modified: Thu, 05 May 2022 00:06:47 GMT
Accept-Ranges: bytes
ETag: "1aa9d-5de388491448c"
Server: Apache
Date: Thu, 05 May 2022 01:34:19 GMT

さらに、今回のケースだとプリフライトリクエスト時はContent-Typeなども考慮する必要がありますが、こちらも自動で付与してくれます。(Access-Control-Allow-Headers)

一点注意があって、アプリケーション側で独自にCORSコードを適用している場合、App Service CORSと併用するとApp Service CORSが優先される仕様となっています。
App Service側の設定は許可オリジンを設定する形なので、それ以上の設定(特定パスのみAllowしたい等)が必要であれば、App ServiceのCORSは使わずに独自で制御コードを実装する必要があります。

Azure Front Doorでの設定

Azure Front DoorではApp ServiceのようにCORS自動有効化機能みたいなものはないので、ルールセットを構成し、レスポンスヘッダーを書き換えます。
リクエストヘッダーのOriginを判定条件とし、Access-Control-Allow-Originを追加しています。

$ curl -I -H "Origin:https://lively-river-022892310.1.azurestaticapps.net" https://hoge0505fd-e7awfdc3g4bxgffc.z01.azurefd.net/image1.png
HTTP/2 200 
content-length: 109213
content-type: image/png
last-modified: Thu, 05 May 2022 00:06:47 GMT
accept-ranges: bytes
etag: "1aa9d-5de388491448c"
access-control-allow-origin: https://lively-river-022892310.1.azurestaticapps.net
x-cache: CONFIG_NOCACHE
x-azure-ref: 04SlzYgAAAAD2CUdQIVIgRq477CufnXIlVFlPMDFFREdFMjMwOQA0Mzg3MmFhNy0zMTYxLTQ1NjItOTBlOC1kNzU5NGZiMWZlOTA=
date: Thu, 05 May 2022 01:35:30 GMT

ただし、今回のケースだとAccess-Control-Allow-Originのみだとプリフライトに失敗します。ルールでヘッダーを設定しているのでAccess-Control-Allow-Headersが必要であればそちらも追加が必要です。

なお、Front DoorのオリジンがApp Serviceの場合は、Originリクエストヘッダーがオリジンまで転送され、App ServiceからAccess-Control-Allow-Originを返却出来るので、App Service側で設定も可能でした。ただしキャッシュヒットの注意が必要そうです。

さいごに

本日は、Azure Front Door と Azure App Service のそれぞれでCORS設定を行う方法を確認しました。
CORSがうまく解決出来ない人がいて一緒に調べていたのですが、試してみると App Serviceが手軽に設定出来て感動しました。
Front Doorはより細かい設定が必要にはなりますが、バックエンドヘッダーをオーバーライド出来るので柔軟性は高いですね。App Serviceの紹介の後半で独自CORSについて言及しましたが、APIに手をいれずにFront Doorでカスタマイズする方法もアリかなと思いました。