Search code examples
c#asp.net-coreasp.net-authentication

HttpClient calling API doesnt not pass cookie auth


Trying to call an API from a controller using HttpClient and the API does not recognize the user as authenticated and logged in. When calling the API from JS I have no issue. I noticed the HttpClient was only sending via HTTP 1.1 and so I upgraded to 2.0 settings the DOTNET_SYSTEM_NET_HTTP_USESOCKETSHTTPHANDLER flag but this made no difference. I have tried all combinations of the HttpClientHandler properties including UseCookies and the request is never authenticated.

        using (var handler = new HttpClientHandler {UseDefaultCredentials = true})
        {
            using (var httpClient = new HttpClient(handler))
            {
                var response = httpClient.GetStringAsync(new Uri($"https://localhost:64366/api/")).Result;
            }
        }

Will move to token based auth in the future but for now would like to understand why there is a difference between calling the API from C# vs JS. This is all HTTPS on localhost using asp net core 2.2.


Solution

  • Difference between JS and C# is that browsers attach cookies automatically to requests and you have to attach cookies manually in C# as juunas mentioned.

    To obtain and use authentication cookie you may use the following pattern

    CookieContainer cookies = new CookieContainer(); //this container saves cookies from responses and send them in requests
    var handler = new HttpClientHandler
    {
        CookieContainer = cookies
    };
    
    var client = new HttpClient(handler);
    
    string authUrl = ""; //your auth url
    string anyUrl = ""; //any url that requires you to be authenticated
    
    var authContent = new FormUrlEncodedContent(
        new List<KeyValuePair<string, string>> {
            new KeyValuePair<string, string>("login", "log_in"),
            new KeyValuePair<string, string>("password", "pass_word")
            }
        );
    
    //cookies will be set on this request
    HttpResponseMessage auth = await client.PostAsync(authUrl, authContent);
    auth.EnsureSuccessStatusCode(); //retrieving result is not required but you will know if something goes wrong on authentication
    
    //and here retrieved cookies will be used
    string result = await client.GetStringAsync(anyUrl);