peter.swallow
peter.swallow

Reputation: 945

HttpClient is sending request cookies from other requests' responses

We have a Web API (.NET Core 5) which passes the request on to another remote Web API.

The Web API grabs some cookies from the incoming request and appends them to the outgoing request.

Normally this works fine and we see the request cookies arriving at the remote Web API.

But when multiple requests are sent simultaneously, the cookies from one incoming request are somehow leaking over into the outgoing request of another.

This even happens when using totally separate users and totally separate browsers.

Things I've tried and confirmed:

The first API has this setup to use HttpClient:

services.AddHttpContextAccessor()
services.AddHttpClient<IRemoteService, RemoteService>()
                .AddHttpMessageHandler<CopyCookieHandler>();
services.AddTransient<CopyCookieHandler>();

where

public class RemoteService : IRemoteService
{
   private HttpClient _client;
   public RemoteService(HttpClient client)
   {
      _client = client;
   }

   public async Task Get()
   {
      var request = new HttpRequestMessage("POST", "http://example.com");
      await MakeCall(request);
   }
}

The CopyCookieHandler is:

public class CopyCookieHandler : DelegatingHandler
{
  public IHttpContextAccessor _context;
  public CopyCookieHandler(IHttpContextAccessor context)
  {
     _context = context;
  }

  protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
  {
     //Copies the incoming request cookie and adds to the outgoing request
     var productId = _context.HttpContext.Request.Cookies["productId"];
     request.Headers.Add(HeaderNames.Cookie, $"productId={productId});

     var response = await base.SendAsync(request, cancellationToken);
     return response;
  }
}

Upvotes: 6

Views: 4889

Answers (1)

peter.swallow
peter.swallow

Reputation: 945

It turns out that, by default, the HttpClientHandler will store the response cookies in a CookieContainer and then append them onto the next request.

This explains why I was seeing extra cookies on the remote API's requests, but they were actually coming from the response of a previously completed request.

This documentation led me to the fix

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/http-requests?view=aspnetcore-5.0#cookies-1

ASP.NET Core documentation: HttpClient & Cookies

So by adding this code:

services.AddHttpClient<IRemoteService, RemoteService>()
    .ConfigurePrimaryHttpMessageHandler(() =>
    {
        return new HttpClientHandler()
        {
            UseCookies = false,
        };
    })
    .AddHttpMessageHandler<CopyCookieHandler>();

will prevent the HttpClientHandler from sharing your cookies between request on your HttpClient.

Upvotes: 5

Related Questions