Skip to content

Commit d9bcd6d

Browse files
authored
Fix client IP address detection to show real user IP instead of AppGateway internal IP (#828)
### Summary & Motivation Fix the Sessions dialog showing the AppGateway's internal IP address (e.g., `10.0.0.54`) instead of the user's real public IP address. This regression was introduced in commit `c67bdac` which added YARP's `AddXForwarded` transform. - Remove YARP's `AddXForwarded()` transform from AppGateway, which was replacing the original `X-Forwarded-For` header set by Azure Container Apps ingress - Update `HttpExecutionContext.ClientIpAddress` to read the `X-Forwarded-For` header directly and extract the first IP address (the original client), with a fallback to `RemoteIpAddress` for local development The previous approach relied on `UseForwardedHeaders` middleware processing the header correctly across multiple proxy hops, but YARP's `AddXForwarded` transform was overwriting the header with the wrong IP before it reached the backend API. ### Checklist - [x] I have added tests, or done manual regression tests - [x] I have updated the documentation, if necessary
2 parents c407373 + 70e27ac commit d9bcd6d

File tree

2 files changed

+13
-8
lines changed

2 files changed

+13
-8
lines changed

application/AppGateway/Program.cs

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using PlatformPlatform.AppGateway.Transformations;
66
using PlatformPlatform.SharedKernel.Configuration;
77
using Scalar.AspNetCore;
8-
using Yarp.ReverseProxy.Transforms;
98

109
var builder = WebApplication.CreateBuilder(args);
1110

@@ -14,12 +13,7 @@
1413
.LoadFromConfig(builder.Configuration.GetSection("ReverseProxy"))
1514
.AddConfigFilter<ClusterDestinationConfigFilter>()
1615
.AddConfigFilter<ApiExplorerRouteFilter>()
17-
.AddTransforms(context =>
18-
{
19-
context.AddXForwarded();
20-
context.RequestTransforms.Add(context.Services.GetRequiredService<BlockInternalApiTransform>());
21-
}
22-
);
16+
.AddTransforms(context => context.RequestTransforms.Add(context.Services.GetRequiredService<BlockInternalApiTransform>()));
2317

2418
if (SharedInfrastructureConfiguration.IsRunningInAzure)
2519
{

application/shared-kernel/SharedKernel/ExecutionContext/HttpExecutionContext.cs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,18 @@ public IPAddress ClientIpAddress
3939
return field = IPAddress.None;
4040
}
4141

42-
// UseForwardedHeaders() middleware already processes X-Forwarded-For and sets RemoteIpAddress
42+
// Read X-Forwarded-For header directly to get client IP (first IP in the chain is the original client)
43+
var forwardedFor = httpContextAccessor.HttpContext.Request.Headers["X-Forwarded-For"].ToString();
44+
if (!string.IsNullOrEmpty(forwardedFor))
45+
{
46+
var clientIp = forwardedFor.Split(',').FirstOrDefault()?.Trim();
47+
if (IPAddress.TryParse(clientIp, out var parsedIpAddress))
48+
{
49+
return field = NormalizeLoopbackAddress(parsedIpAddress);
50+
}
51+
}
52+
53+
// Fall back to RemoteIpAddress for local development without proxies
4354
var remoteIpAddress = httpContextAccessor.HttpContext.Connection.RemoteIpAddress ?? IPAddress.None;
4455
return field = NormalizeLoopbackAddress(remoteIpAddress);
4556
}

0 commit comments

Comments
 (0)