しばやん雑記

Azure Serverless とメイドさんが大好きなフリーランスのプログラマーのブログ

Azure Front Door や Application Gateway と App Service Authentication を組み合わせて利用する

App Service を利用したアーキテクチャでは、フロントエンドに Front Door や Application Gateway といった L7 のロードバランサーを追加する構成を組むことがそれなりにあります。

特に Front Door は CDN と L7 ロードバランサが組み合わされたサービスなので、静的コンテンツをキャッシュしつつ API などのリクエストはバックエンドプールに分散させることが簡単に実現出来ます。

実際に Front Door のチュートリアルでも地理分散された App Service の前に Front Door を 1 つ作成して、可用性を高める構成を取っています。DNS レベルでルーティングを行う Traffic Manager よりも、Front Door の方が制御しやすくバックエンド選択のパラメータが多いです。

設定が反映されるまで地味に時間がかかるのが難点ではあるのですが、その辺りは若干 Front Door Standard / Premium で改善されそうな気配があるので期待しています。

Front Door 自体の話はこれぐらいにして、本題である Front Door や Application Gateway といった L7 ロードバランサと App Service Authentication を組み合わせた時に発生する問題と、解決策の話をします。

Front Door を作成し App Service Authentication を設定

適当に Front Door を作成して、バックエンドには App Service を追加しておきます。App Service では予め App Service Authentication を使って Azure AD 認証を有効にしてあります。

f:id:shiba-yan:20210908001211p:plain

今回は Front Door にカスタムドメインの設定までは行っていませんが、フロントに Front Door を追加すると当然ながらホスト名が App Service のデフォルトではなくなるので、Azure AD のアプリケーション登録からリダイレクト URI を変更します。

単純にホスト名を azurewebsites.net から azurefd.net に置き換えるだけで良いです。カスタムドメインを設定した場合は、それに置き換えれば問題ありません。

f:id:shiba-yan:20210907234213p:plain

Front Door と Azure AD アプリケーションの設定はこれだけです。作業自体は難しくないはずです。

実際にアクセスしてみると、Azure AD のログイン画面にリダイレクトしたタイミングで、以下のようにリダイレクト URI のミスマッチエラーが出るようになります。

f:id:shiba-yan:20210907234301p:plain

OpenID Connect に対応したプロバイダーを使っていると、たまに設定忘れで表示されるものにはなりますが、今回は正しいリダイレクト URI を設定しているのに表示されます。

原因は非常に単純で Azure AD のログイン画面にリダイレクトされる時のクエリパラメータを確認するとわかります。重要な redirect_uri には見てわかる通り、アクセスに使用した azurefd.net ではなくバックエンド App Service の azurewebsites.net が渡されています。

f:id:shiba-yan:20210907234547p:plain

この時点で詳しい方は原因が分かったと思いますが、App Service Authentication が X-Forwarded-Host を正しく扱っていないことが原因です。

以下のエントリで書いたように、Front Door は一般的な L7 ロードバランサと同様に X-Forwarded-* 系ヘッダーをバックエンドへのリクエストに追加しますが、App Service Authentication は Host ヘッダーのみを見てリダイレクト先を作成しているようです。

App Service Authentication の問題なので ASP.NET Core などで自前で実装すると、大体は X-Forwarded-Host を正しく扱えるのでこのような問題は発生しないのですが、この手の認証を自前で実装するのは避けているのでコードを書かずに解決します。

これまでは解決しようがなかったのですが、App Service Authentiation の V2 からロードバランサー下にある場合の処理が改善され、設定の変更で対応できるようになりました。

新しい App Service Authentication V2 の設定を有効化

Azure Portal に新しい Authentication 設定が追加されたタイミングで、プラットフォームと ARM の両方で実装が新しくなり、今回のようなロードバランサー下のシナリオに対応できるようになりました。

リファレンスでは存在を知っていたのですが、ドキュメント化がまともにされていなかったので App Service Team Blog の記事によって、初めて動作と設定方法が公開されました。

具体的には forwardProxy の中にある convention プロパティの値を、デフォルトの NoProxy から Standard に変更すると、標準となっている X-Forwarded-Host を扱うようになります。

App Service Authentication のランタイムは V1 と V2 で共通ですが、この設定を有効化するためには V2 に移行する必要があります。V2 への移行は Azure Portal からは簡単に行えますが、ARM Template や Terraform を使っている場合は手間がかかります。

今回は最初から Auth Settings V2 で作っているので、移行の手順に関しては省略します。

Auth Settings V2 のエンドポイントは PATCH リクエストを受け付けてくれないので、以下のように ARM Explorer 上でサクッと編集するのが一番簡単です。

f:id:shiba-yan:20210907235451p:plain

Application Gateway のように X-Forwarded-Host 以外のヘッダーを送ってくる場合は、Custom に設定した上で customHostHeaderName に利用するヘッダー名を設定すればよいです。関係ないですが apiPrefix を変更すればエンドポイントを .auth 以外に変更することも出来ます。

設定を変更後に最初と同じように azurefd.net にアクセスすると、今度は redirect_uri が Front Door を指したままになっているので、Azure AD 認証も問題なく通るようになりました。

f:id:shiba-yan:20210907235839p:plain

今回のようにバックエンドの App Service に対してアクセス制限を設定していない場合は、リダイレクト先が異なっていても Azure AD 側の設定漏れによってはログイン出来てしまうケースもあるので、アクセス制限込みで設定を忘れないようにしたいです。

Static Web Apps では現時点で問題あり

App Service Environment がバックエンドで使われている Static Web Apps でも、Custom Authentiation を有効化しつつ Front Door などの L7 ロードバランサーを組み合わせて利用すると、同様の問題が発生します。

残念ながら Static Web Apps では App Service のように設定変更が行えないため、現時点では回避できない問題となっていますが、来月あたりには対応するという返事は貰っています。

どのように設定するのかはまだ分からないですが、恐らく staticwebapp.config.json に同じような設定が追加されるのだと思います。解消されるまでは上の Issue をウォッチしていきたいと思います。