06-21-2019, 04:01 AM
Forwarded Headers Middleware Updates in .NET Core 3.0 preview 6
<div style="margin: 5px 5% 10px 5%;"><img src="http://www.sickgaming.net/blog/wp-content/uploads/2019/06/forwarded-headers-middleware-updates-in-net-core-3-0-preview-6.jpg" width="58" height="58" title="" alt="" /></div><div><div class="row justify-content-center">
<div class="col-md-4">
<div><img src="http://www.sickgaming.net/blog/wp-content/uploads/2019/06/forwarded-headers-middleware-updates-in-net-core-3-0-preview-6.jpg" width="58" height="58" alt="Avatar" class="avatar avatar-58 wp-user-avatar wp-user-avatar-58 photo avatar-default"></div>
</div>
</div>
<div class="entry-meta">
<p>June 20th, 2019</p>
</p></div>
<p><!-- .entry-meta --> </p>
<p>With the ASP.NET Core 2.1 release, we included <code>UseHsts</code> and <code>UseHttpRedirection</code> by default. These methods put a site into an infinite loop if deployed to an Azure Linux App Service, Azure Linux virtual machine (VM), or behind any other reverse proxy besides IIS. TLS is terminated by the reverse proxy, and Kestrel isn’t made aware of the correct request scheme.</p>
<p>OAuth and OIDC also fail in this configuration because they generate incorrect redirects. Calls to <code>UseIISIntegration</code> add and configure forwarded headers middleware when running behind IIS, but there’s no matching automatic configuration for Linux (Apache or Nginx integration). The fix for this issue is discussed in more detail in the doc article <a href="https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-2.2#forward-the-scheme-for-linux-and-non-iis-reverse-proxies">Forward the scheme for Linux and non-IIS reverse proxies</a>.</p>
<h2>Configuration-only Wire-up in Preview 6</h2>
<p>With the updates in .NET Core 3 preview 6, you no longer need to call the middleware explicitly, as the host logic has been pre-wired to enable the Forwarded Headers Middleware by default as long as the <code>ASPNETCORE_FORWARDEDHEADERS_ENABLED</code> environment variable has been set to <code>true</code>. Turning on the Forwarded Headers Middleware is as simple as setting the <code>ASPNETCORE_FORWARDEDHEADERS_ENABLED</code> setting in the Azure Portal’s configuration blade for any App Service running on Linux or in a container.</p>
<p><img src="http://www.sickgaming.net/blog/wp-content/uploads/2019/06/forwarded-headers-middleware-updates-in-net-core-3-0-preview-6.png" alt="Enabling the Forwarded Headers Middleware via config"></p>
<p>Once this setting is set to true, the middleware starts working, and features dependent on <code>Request.IsHttps</code> resulting to <code>true</code> begin to function as expected.</p>
<h2>Resolving the issue with ASP.NET Core 2.x Apps Today</h2>
<p>If you’re currently building an ASP.NET Core 2.x app and want to run it on App Service for Linux now, there’s a workaround that will be future-proof when the updates come out for 3.0.</p>
<p>To forward the scheme from the proxy in non-IIS scenarios, add and configure Forwarded Headers Middleware. In <code>Startup.cs</code>, use the following code:</p>
<pre><code class="csharp">// using Microsoft.AspNetCore.HttpOverrides; public void ConfigureServices(IServiceCollection services)
{ if (string.Equals( Environment.GetEnvironmentVariable("ASPNETCORE_FORWARDEDHEADERS_ENABLED"), "true", StringComparison.OrdinalIgnoreCase)) { services.Configure<forwardedheadersoptions>(options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; // Only loopback proxies are allowed by default. // Clear that restriction because forwarders are enabled by explicit // configuration. options.KnownNetworks.Clear(); options.KnownProxies.Clear(); }); }
} public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{ app.UseForwardedHeaders();
}
</code></pre>
<p>If you enable your ASP.NET Core 2.x apps with this workaround today, when you’re ready to upgrade to 3.0, you’ll already have the right configuration setting in place.</p>
<h2>Base Image Update</h2>
<p>The base images used by the App Service team to streamline the creation of ASP.NET Core apps will soon be updated so that the <code>ASPNETCORE_FORWARDEDHEADERS_ENABLED</code> environment variable will be set to <code>true</code>. Once they’re updated, you won’t even need to explicitly set the environment variable; it’ll be enabled by default.</p>
<h2>Try it Out</h2>
<p>If you’re new to building ASP.NET Core apps using containers, the App Service options for Linux and Container-based hosting offer a great place to get started. The docs are loaded with guidance and examples, from how to <a href="https://docs.microsoft.com/en-us/azure/app-service/containers/quickstart-dotnetcore">Run a .NET Core app in App Service on Linux</a> to accessing a <a href="https://docs.microsoft.com/en-us/azure/app-service/containers/tutorial-dotnetcore-sqldb-app">SQL Server Database from an ASP.NET Core app running in App Service Linux</a>.</p>
<div class="authorinfoarea">
<div><img src="http://www.sickgaming.net/blog/wp-content/uploads/2019/06/forwarded-headers-middleware-updates-in-net-core-3-0-preview-6-1.jpg" width="96" height="96" alt="Avatar" class="avatar avatar-96 wp-user-avatar wp-user-avatar-96 photo avatar-default"></div>
<div>
<h5><a class="no-underline" aria-label=" Brady Gaster" target="_blank" href="https://devblogs.microsoft.com/aspnet/author/bradygmicrosoft-com/" rel="noopener noreferrer"> Brady Gaster</a></h5>
<p>Senior Program Manager, ASP.NET Core</p>
<p><strong>Follow </strong> <a class="no-underline stayinformed" aria-label=" Brady Gaster Twitter profile" target="_blank" href="https://twitter.com/bradygaster" rel="noopener noreferrer"><i class="fa fa-twitter"></i></a><a class="no-underline stayinformed" aria-label=" Brady Gaster GitHub profile" target="_blank" href="https://github.com/bradygaster" rel="noopener noreferrer"><i class="fa fa-github"></i></a><a class="no-underline stayinformed hvr-pop" aria-label=" Brady Gaster RSS Feed" target="_blank" href="https://devblogs.microsoft.com/aspnet/author/bradygmicrosoft-com/feed/" rel="noopener noreferrer"></a></p>
</p></div>
</p></div>
</div>
<div style="margin: 5px 5% 10px 5%;"><img src="http://www.sickgaming.net/blog/wp-content/uploads/2019/06/forwarded-headers-middleware-updates-in-net-core-3-0-preview-6.jpg" width="58" height="58" title="" alt="" /></div><div><div class="row justify-content-center">
<div class="col-md-4">
<div><img src="http://www.sickgaming.net/blog/wp-content/uploads/2019/06/forwarded-headers-middleware-updates-in-net-core-3-0-preview-6.jpg" width="58" height="58" alt="Avatar" class="avatar avatar-58 wp-user-avatar wp-user-avatar-58 photo avatar-default"></div>
</div>
</div>
<div class="entry-meta">
<p>June 20th, 2019</p>
</p></div>
<p><!-- .entry-meta --> </p>
<p>With the ASP.NET Core 2.1 release, we included <code>UseHsts</code> and <code>UseHttpRedirection</code> by default. These methods put a site into an infinite loop if deployed to an Azure Linux App Service, Azure Linux virtual machine (VM), or behind any other reverse proxy besides IIS. TLS is terminated by the reverse proxy, and Kestrel isn’t made aware of the correct request scheme.</p>
<p>OAuth and OIDC also fail in this configuration because they generate incorrect redirects. Calls to <code>UseIISIntegration</code> add and configure forwarded headers middleware when running behind IIS, but there’s no matching automatic configuration for Linux (Apache or Nginx integration). The fix for this issue is discussed in more detail in the doc article <a href="https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-2.2#forward-the-scheme-for-linux-and-non-iis-reverse-proxies">Forward the scheme for Linux and non-IIS reverse proxies</a>.</p>
<h2>Configuration-only Wire-up in Preview 6</h2>
<p>With the updates in .NET Core 3 preview 6, you no longer need to call the middleware explicitly, as the host logic has been pre-wired to enable the Forwarded Headers Middleware by default as long as the <code>ASPNETCORE_FORWARDEDHEADERS_ENABLED</code> environment variable has been set to <code>true</code>. Turning on the Forwarded Headers Middleware is as simple as setting the <code>ASPNETCORE_FORWARDEDHEADERS_ENABLED</code> setting in the Azure Portal’s configuration blade for any App Service running on Linux or in a container.</p>
<p><img src="http://www.sickgaming.net/blog/wp-content/uploads/2019/06/forwarded-headers-middleware-updates-in-net-core-3-0-preview-6.png" alt="Enabling the Forwarded Headers Middleware via config"></p>
<p>Once this setting is set to true, the middleware starts working, and features dependent on <code>Request.IsHttps</code> resulting to <code>true</code> begin to function as expected.</p>
<h2>Resolving the issue with ASP.NET Core 2.x Apps Today</h2>
<p>If you’re currently building an ASP.NET Core 2.x app and want to run it on App Service for Linux now, there’s a workaround that will be future-proof when the updates come out for 3.0.</p>
<p>To forward the scheme from the proxy in non-IIS scenarios, add and configure Forwarded Headers Middleware. In <code>Startup.cs</code>, use the following code:</p>
<pre><code class="csharp">// using Microsoft.AspNetCore.HttpOverrides; public void ConfigureServices(IServiceCollection services)
{ if (string.Equals( Environment.GetEnvironmentVariable("ASPNETCORE_FORWARDEDHEADERS_ENABLED"), "true", StringComparison.OrdinalIgnoreCase)) { services.Configure<forwardedheadersoptions>(options => { options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto; // Only loopback proxies are allowed by default. // Clear that restriction because forwarders are enabled by explicit // configuration. options.KnownNetworks.Clear(); options.KnownProxies.Clear(); }); }
} public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{ app.UseForwardedHeaders();
}
</code></pre>
<p>If you enable your ASP.NET Core 2.x apps with this workaround today, when you’re ready to upgrade to 3.0, you’ll already have the right configuration setting in place.</p>
<h2>Base Image Update</h2>
<p>The base images used by the App Service team to streamline the creation of ASP.NET Core apps will soon be updated so that the <code>ASPNETCORE_FORWARDEDHEADERS_ENABLED</code> environment variable will be set to <code>true</code>. Once they’re updated, you won’t even need to explicitly set the environment variable; it’ll be enabled by default.</p>
<h2>Try it Out</h2>
<p>If you’re new to building ASP.NET Core apps using containers, the App Service options for Linux and Container-based hosting offer a great place to get started. The docs are loaded with guidance and examples, from how to <a href="https://docs.microsoft.com/en-us/azure/app-service/containers/quickstart-dotnetcore">Run a .NET Core app in App Service on Linux</a> to accessing a <a href="https://docs.microsoft.com/en-us/azure/app-service/containers/tutorial-dotnetcore-sqldb-app">SQL Server Database from an ASP.NET Core app running in App Service Linux</a>.</p>
<div class="authorinfoarea">
<div><img src="http://www.sickgaming.net/blog/wp-content/uploads/2019/06/forwarded-headers-middleware-updates-in-net-core-3-0-preview-6-1.jpg" width="96" height="96" alt="Avatar" class="avatar avatar-96 wp-user-avatar wp-user-avatar-96 photo avatar-default"></div>
<div>
<h5><a class="no-underline" aria-label=" Brady Gaster" target="_blank" href="https://devblogs.microsoft.com/aspnet/author/bradygmicrosoft-com/" rel="noopener noreferrer"> Brady Gaster</a></h5>
<p>Senior Program Manager, ASP.NET Core</p>
<p><strong>Follow </strong> <a class="no-underline stayinformed" aria-label=" Brady Gaster Twitter profile" target="_blank" href="https://twitter.com/bradygaster" rel="noopener noreferrer"><i class="fa fa-twitter"></i></a><a class="no-underline stayinformed" aria-label=" Brady Gaster GitHub profile" target="_blank" href="https://github.com/bradygaster" rel="noopener noreferrer"><i class="fa fa-github"></i></a><a class="no-underline stayinformed hvr-pop" aria-label=" Brady Gaster RSS Feed" target="_blank" href="https://devblogs.microsoft.com/aspnet/author/bradygmicrosoft-com/feed/" rel="noopener noreferrer"></a></p>
</p></div>
</p></div>
</div>