ASP.NET Coreを特にLinuxなどで動かす場合、Kestrelを使うことが多いのですが、Kestrel自体はシンプルなサーバーなのでフロントにHAProxy
やnginx
などのプロキシーサーバーを配置することが多くなります。さらにHTTPSでアクセスするようにする場合、証明書はKestrel側ではなくてプロキシサーバー側に配置して、プロキシサーバーからKestrelまでは(プライベートネットワークだし)HTTPで通信するケースもあるかと思います。その場合、ASP.NET Core側でRequest.Scheme
*1はhttp
になります。これをhttps
にしたい場合のお話です。
OpenID ConnectやAzure AD B2Cなどの認証などのために、リクエストをリダイレクトする場合、ユーザーがアプリにリクエストしたURLを基にcallbackするURLを生成するため、Request.Scheme
が使われます。このとき、リバースプロキシ経由でHTTPリクエストをKestrelが受信している場合、当然のごとくRequest.Scheme
はhttp
になります。
認証サーバーに認証後にCallbackするURLも一緒に渡し場合、Request.Scheme
を基にURLを構築している場合*2このURLがhttpになります。認証サービスプロバイダー側がこれを許可していれば別ですが、例えばAzure AD B2Cの場合https
でないと許可されないため動きません。他にもうまくいかないプロバイダーや認証以外のサービスもあると思います。そこで、ASP.NET Core側にhttpsでユーザーからリクエストは送信されて、リバースプロキシ経由でhttpになっていることを伝える必要がでてきます。
実はこの設定については、タイトルがnginxなので自分はすっかり読み飛ばしていたのですが、ASP.NET Coreのドキュメントにも載っています。
まず前提条件として、リバースプロキシサーバーがHTTPリクエストをKestrelに送信する場合に、X-Forwarded-Proto
というHTTPヘッダーにオリジナルのリクエストのプロトコルを値にしたヘッダーを追加している必要があります。多くの場合、X-Forwarded-For
と併せて設定されているのではないかと思います。
この条件のもと次のようなミドルウェアを追加するコードをStartup
クラスのConfigure
メソッドに記述します。認証サービスで利用する場合は、サンプルのようにUseAuthentication
メソッドの前に記述する必要があります。
//using using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.HttpOverrides; // app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto }); app.UseAuthentication();
このメソッドはMicrosoft.AspNetCore.HttpOverrides
というNuGetライブラリで提供されていますが、Microsoft.AspNetCore.All
が依存しているのでこれを参照している場合は明示的に追加する必要はありません。
これでこのミドルウェアを通った後は、HTTPヘッダーからX-Forwarded-Proto
がなくなり、Request.Scheme
がhttps
を返すようになるのでめでたし、ということになります。