IIS Reverse Proxy
1 TopicHow to Properly Configure IIS Reverse Proxy for ASP.NET Core Applications Secured with Entra ID
If you’ve ever worked on an ASP.NET Core application protected with Entra ID, you might have encountered an issue where the backend server URL appears as the redirect URI instead of the IIS Reverse Proxy URL. This is because ASP.NET Core applications use the backend server’s hostname to generate the redirect URI. While this behavior is the default, it can be problematic. While you can work around this by manually setting the redirect URI to the ARR/IIS Reverse Proxy endpoint in your code as follows: builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd")); builder.Services.Configure<OpenIdConnectOptions>(options => { options.Events.OnRedirectToIdentityProvider = context => { context.ProtocolMessage.RedirectUri = "https://arr.local.lab"; return Task.FromResult(0); }; }); It isn’t the most elegant solution, especially in environments where configuration changes might often be required. Instead, using Forwarded Headers offers a cleaner, more scalable approach. In this post, I’ll walk you through how to resolve this issue using Forwarded Headers. ASP.NET Core provides a ForwardedHeaders Middleware , which reads headers such as X-Forwarded-Host and X-Forwarded-Proto. These headers replace values in HttpContext such as HttpContext.Request.Host and HttpContext.Request.Scheme. By passing these headers appropriately from IIS Reverse Proxy, we can resolve the redirect URI issue. But IIS reverse proxy or server farms doesn't send X-Forwarded-Host & X-Forwarded-Proto headers by default. You’ll need to configure IIS to include these headers using the URL Rewrite feature. To do so, follow these steps: Set Server Variables Open the URL Rewrite module in the IIS Manager Console and Select View Server Variables. Add following Server Variables: HTTP_X_Forwarded_Host HTTP_X_Forwarded_Proto Edit Inbound Rules Once Server Variables are added, select the concerned reverse proxy inbound rule and select Edit under Inbound rules in Actions Pane. Add the Server Variables to the inbound rule: Map HTTP_X_Forwarded_Host to {HTTP_HOST} Map HTTP_X_Forwarded_Proto to https Once IIS is configured to pass forwarded headers, the application needs to process them. Add ForwardedHeaders Middleware in your ASP.NET Core application and configure ForwardedHeadersOptions as follows: using Microsoft.AspNetCore.HttpOverrides; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme) .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd")); builder.Services.AddAuthorization(options => { // By default, all incoming requests will be authorized according to the default policy. options.FallbackPolicy = options.DefaultPolicy; }); builder.Services.AddRazorPages() .AddMicrosoftIdentityUI(); builder.Services.Configure<ForwardedHeadersOptions>(options => { options.KnownProxies.Add(IPAddress.Parse("10.160.7.4")); // Reverse Proxy IP address options.ForwardedHeaders = ForwardedHeaders.XForwardedProto | ForwardedHeaders.XForwardedHost; }); var app = builder. Build(); app.UseForwardedHeaders(); // ForwardedHeaders Middleware // Configure the HTTP request pipeline. if (!app.Environment.IsDevelopment()) { app.UseExceptionHandler("/Error"); app.UseHsts(); } app.UseHttpsRedirection(); app.UseRouting(); app.UseAuthentication(); app.UseAuthorization(); app.MapStaticAssets(); app.MapRazorPages() .WithStaticAssets(); app.MapControllers(); app.Run(); Note: Order of the Middleware is important. Ensure ForwardedHeaders Middleware is called before any other middleware in the pipeline. Make sure to add the IP address of your ARR/IIS Reverse Proxy to the KnownProxies list. Alternatively, you can use KnownNetwork to set IP range. With these configurations, X-Forwarded-Host and X-Forwarded-Proto headers sent from IIS Reverse Proxy will replace the Host and Scheme in HttpContext. This ensures that the redirect URI correctly points to the IIS Reverse Proxy endpoint, resolving the issue seamlessly. Further Reading: Refer to these resources for more information: Configure ASP.NET Core to work with proxy servers and load balancers | Microsoft Learn Setting HTTP request headers and IIS server variables | Microsoft Learn IIS Server Variables | Microsoft Learn Hope this guide helps!183Views2likes0Comments