dotnet / dotnet/runtime

`Authorization` header should be preserved when auto-redirecting to the same domain with `HttpClient`

Open
#122,609 12 comments 4 reactions 0 assignees View on GitHub
area-System.Net.Http enhancement
Dominant language
C#
Stars
18.3k
Forks
5.6k
PR merge metrics
PR metrics pending

Description

### Description

When `AllowAutoRedirect` is set to `true` (default behavior for both `HttpClientHandler` as well as `SocketsHttpHandler`) the `Authorization` header is stripped out when making the call towards the redirected address.

As the documentation states (on both):
- https://learn.microsoft.com/en-us/dotnet/api/system.net.http.httpclienthandler.allowautoredirect?view=net-10.0#remarks
- https://learn.microsoft.com/en-us/dotnet/api/system.net.http.socketshttphandler.allowautoredirect?view=net-10.0#remarks
> The Authorization header is cleared on auto-redirects and the handler automatically tries to re-authenticate to the redirected location. No other headers are cleared.

I understand this is a security feature, to avoid presenting unintended authentication values to a different service. However, it doesn't make sense to strip the headers when the target is the same as the original request.

For instance, this is what `kiota`'s `RedirectHandler` does:

https://github.com/microsoft/kiota-dotnet/blob/d2f5bdad58f77f8cc040dc717ec46e03e7341d4e/src/http/httpClient/Middleware/RedirectHandler.cs#L122-L127

It conditionally removes the header only when the schema or host properties differ, and preserves it otherwise.

I spent hours yesterday on an issue related to this because we rely on a redirect (302) from an authorized endpoint to another endpoint on the same API, which also requires authorization.

When configuring the standard `kiota` proxy with that API, the redirection call happens with an empty `Authorization` header because of this standard behavior (specifically from `SocketsHttpHandler` in our case).

### Reproduction Steps

Using a `HttpClient` with either a `HttpClientHandler` or a `SocketsHttpHandler` and the `AllowAutoRedirect` set to `true` (the default value), make an authorized call to an API that results in one of the 4 HTTP redirection status codes with a `Location` header pointing to another route in the same API/domain.

### Expected behavior

I would expect the authorization header to be preserved on redirects to the same scheme/host, like what the `kiota` implementation does.

### Actual behavior

Using a `HttpClient` with either a `HttpClientHandler` or a `SocketsHttpHandler` results in stripped `Authorization` headers on all redirects.

### Regression?

_No response_

### Known Workarounds

To resolve the issue, we had to manually turn off `AllowAutoRedirect` on the handler, and then leverage `kiota`'s handler instead:

```csharp
hostApplicationBuilder.Services
.AddKiotaHttpHandlers()
.ConfigureHttpClientDefaults(b => b
.ConfigurePrimaryHttpMessageHandler((handler, _) => ((SocketsHttpHandler)handler).AllowAutoRedirect = false)
.AddKiotaHandlers())
```

This feels super unintuitive and it would be much nicer if the default redirection behavior on `SocketsHttpHandler` took the host into account as well.

### Configuration

.NET 10
Windows and Linux x64

### Other information

_No response_

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.