HTTPS Link Generation for ASP.NET Core App hosted in Azure Container Apps
Azure Container Apps is a fully managed Kubernetes-based application platform that can help us deploy apps from code or containers without orchestrating complex infrastructures. ASP.NET Core based containers can be deployed into Azure Container Apps with free managed SSL certificate too. You can find an example in article Use Bicep to deploy Azure Container Apps with a free managed certificate. As standard practice, the ASP.NET Core application will listen on HTTP port 80 (or 8080 for .NET 8). Azure Container Apps ingress will use the certificate you configured to secure the connection with the request client. However this can cause unexpected behavior - ASP.NET Core generates absolute URLs with HTTP as protocol.
Example issue
I encountered the following error when migrating my app to container. The error occurred with external sign-in with Microsoft account using OAuth 2.0. Details about how to setup can be found in Microsoft Account external login setup with ASP.NET Core | Microsoft Learn.
This error occurs because the original request protocol HTTPS is not passed to the container hence a redirect URI with http was generated. Since it is not matching with the configured URI in Azure AD (using HTTPS), the error was thrown out.
Sorry, but we’re having trouble signing you in.
AADSTS50011: The redirect URI 'http://***/signin-microsoft' specified in the request does not match the redirect URIs configured for the application '***'. Make sure the redirect URI sent in the request matches one added to your application in the Azure portal. Navigate to https://aka.ms/redirectUriMismatchError to learn more about how to fix this.
Similar error can occur with sign with Google, Facebook or other accounts.
To fix this error, we need to ensure the application generates HTTPS absolute URLs.
Forwarded headers
The above issue can be fixed by using header forward middleware. It was supported since ASP.NET Core 3.1. It is common that HTTPS requests are proxied via HTTP for ASP.NET Core apps hosted using IIS/ASP.NET Core Module, Nginx, or Apache. Proxy servers, load balancers, and other network appliances. By conventions, proxies forward original information in headers, for example, X-Forwarded-For, X-Forwarded-Proto and X-Forwarded-Host.
We can use forwarded headers in our application so that link generation will generate HTTPS URLs instead of HTTP ones.
The following is an example of how to do that in StartUp.cs:
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
// Configure forwarded headers
services.Configure<ForwardedHeadersOptions>(options =>
{
options.ForwardedHeaders =
ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// Use forwarded headers
app.UseForwardedHeaders();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
Sometimes it may not work and one approach to address that is to directly change request context protocol to HTTPS:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.Use((context, next) =>
{
context.Request.Scheme = "https";
return next();
});
}
To learn more about forwarded headers in ASP.BET Core, refer to the link in References section.
References
Configure ASP.NET Core to work with proxy servers and load balancers | Microsoft Learn