Skip to content

Commit a62a63b

Browse files
fix(auth): honor ASPNETCORE_FORWARDEDHEADERS_ENABLED for ACA (#1153)
## Why GitHub OAuth login on dev was generating an `http://` callback URL and failing with `redirect_uri is not associated with this application`. The deployment now uses `ASPNETCORE_FORWARDEDHEADERS_ENABLED=true`, so app-level forwarded-header setup must not conflict with ASP.NET Core's built-in handling. ## What changed - `AddTrustedForwardedHeaders` now exits early when `ASPNETCORE_FORWARDEDHEADERS_ENABLED=true`. - `Program.cs` skips manual `app.UseForwardedHeaders()` when that env var is enabled to avoid redundant middleware execution. - Updated the forwarded-header configuration error message to document the env-var-based option for platform-managed proxies like Azure Container Apps. ## Notes for reviewers This keeps the existing explicit CIDR path intact for environments that use `ForwardedHeaders:TrustedProxyCidrs`/`TrustedProxies`, while making ACA's env-var path safe and non-conflicting.
1 parent 02cc370 commit a62a63b

2 files changed

Lines changed: 18 additions & 3 deletions

File tree

EssentialCSharp.Web/Extensions/IServiceCollectionExtensions.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ public static void AddCaptchaService(this IServiceCollection services, IConfigur
1818

1919
public static void AddTrustedForwardedHeaders(this IServiceCollection services, IConfiguration configuration, IHostEnvironment environment)
2020
{
21+
// When ASPNETCORE_FORWARDEDHEADERS_ENABLED=true (recommended for Azure Container Apps),
22+
// ASP.NET Core's built-in startup filter handles ForwardedHeaders with all proxies trusted.
23+
// Skip manual configuration to avoid a conflicting no-trusted-proxies throw on startup.
24+
if (string.Equals(configuration["ASPNETCORE_FORWARDEDHEADERS_ENABLED"], "true", StringComparison.OrdinalIgnoreCase))
25+
return;
26+
2127
services.Configure<ForwardedHeadersOptions>(options =>
2228
{
2329
options.ForwardedHeaders =
@@ -37,7 +43,8 @@ public static void AddTrustedForwardedHeaders(this IServiceCollection services,
3743
{
3844
throw new InvalidOperationException(
3945
"Forwarded headers are enabled but no trusted proxies are configured. " +
40-
"Set ForwardedHeaders:TrustedProxyCidrs or ForwardedHeaders:TrustedProxies.");
46+
"Set ForwardedHeaders:TrustedProxyCidrs or ForwardedHeaders:TrustedProxies, " +
47+
"or set ASPNETCORE_FORWARDEDHEADERS_ENABLED=true for platform-managed proxies (e.g. Azure Container Apps).");
4148
}
4249
return;
4350
}

EssentialCSharp.Web/Program.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -481,7 +481,12 @@ await McpJsonRpcResponseWriter.WriteErrorAsync(
481481
}
482482
});
483483
});
484-
app.UseForwardedHeaders();
484+
// Skip manual UseForwardedHeaders when ASPNETCORE_FORWARDEDHEADERS_ENABLED=true;
485+
// the built-in startup filter already called it before this pipeline runs.
486+
if (!string.Equals(app.Configuration["ASPNETCORE_FORWARDEDHEADERS_ENABLED"], "true", StringComparison.OrdinalIgnoreCase))
487+
{
488+
app.UseForwardedHeaders();
489+
}
485490

486491
// Build dynamic CSP — TryDotNet origin comes from runtime config
487492
string? tryDotNetOrigin = app.Configuration["TryDotNet:Origin"];
@@ -532,7 +537,10 @@ await McpJsonRpcResponseWriter.WriteErrorAsync(
532537
else
533538
{
534539
app.UseDeveloperExceptionPage();
535-
app.UseForwardedHeaders();
540+
if (!string.Equals(app.Configuration["ASPNETCORE_FORWARDEDHEADERS_ENABLED"], "true", StringComparison.OrdinalIgnoreCase))
541+
{
542+
app.UseForwardedHeaders();
543+
}
536544
}
537545

538546
app.MapHealthChecks("/health").DisableRateLimiting();

0 commit comments

Comments
 (0)