3

I've trying to pass Windows Authentication to a WebProxy, so that a user doesn't have to type in his login data manually. The use case is a proxy server which checks authentication against a LDAP/AD server, while the users have to change their password periodically.

I've got the following code:

private void button1_ClickAsync(object sender, EventArgs e) {
    Url = "http://local.adress/test";
    Execute();
}

private void button2_Click(object sender, EventArgs e) {
    Url = "https://maps.googleapis.com/maps/api/timezone/json";
    Execute();
}

private void Execute() {
    var handler = new HttpClientHandler();
    handler.DefaultProxyCredentials = CredentialCache.DefaultCredentials;
    handler.UseDefaultCredentials = true;
    handler.UseProxy = true;
    handler.Proxy = WebRequest.DefaultWebProxy;
    handler.Proxy.Credentials = new NetworkCredential("mydomainuser", "mydomainpassword");
    //handler.Proxy.Credentials = CredentialCache.DefaultNetworkCredentials;

    var client = new HttpClient(handler);
    Task<string> response = TestConnection(client, Url);
}

private async Task<string> TestConnection(HttpClient client, string url) {
    try {
        using (HttpResponseMessage result = await client.GetAsync(url)) {
            string res = await result.Content.ReadAsStringAsync().ConfigureAwait(false);
            Console.WriteLine("content: " + res);
            return result.ToString();
        }
    } catch (Exception e) {
        Console.WriteLine("error: " + e.Message);
        return e.ToString();
    }
}

When defining the credentials manually (as you can see in the Execute method), everythings works as expected. I've checked the proxy log files to be sure the request is really forwarded through the proxy.

Since it's my goal to spare the user to type in his probably periodically changing password, I've tried to pass the credentials via the CredentialCache.DefaultNetworkCredentials (I've also tried CredentialCache.DefaultCredentials). While executing the request the proxy logs an DENIED and my client returns HTTP error code 407.

Am I missing something obvious? I know there are countless questions on this topic but nothing seems to solve this problem.

tg24
  • 161
  • 3
  • 22
  • Is this a web application or a client side application? If it is a web application hosted on IIS, what is the user under which the app pool is running? – Krishna Chaithanya Muthyala Jul 23 '19 at 08:03
  • It's a client side application running with WinForms under Windows 10, no IIS involved. – tg24 Jul 23 '19 at 08:59
  • Did you check what values are returned when you access UserName and Password properties of CredentialCache.DefaultNetworkCredentials? Are they matching with the user you wanted to use? – Krishna Chaithanya Muthyala Jul 23 '19 at 11:36
  • 1
    Does your proxy support that? Implicit Windows credentials (DefaultNetworkCredentials) are not a user + password. – Simon Mourier Jul 23 '19 at 11:45
  • @KrishnaChaithanyaMuthyala [ms docs](https://learn.microsoft.com/de-de/dotnet/api/system.net.credentialcache.defaultcredentials?view=netframework-4.8) states that credentials are not visible. – tg24 Jul 23 '19 at 13:55
  • @SimonMourier [ms docs](https://learn.microsoft.com/de-de/dotnet/api/system.net.credentialcache.defaultcredentials?view=netframework-4.8) states "For a client-side application, these are usually the Windows credentials (user name, password, and domain) of the user running the application.", so I assumed that the username and password are included. Does this mean this isn't possible the way I want to do it? – tg24 Jul 23 '19 at 13:57
  • 1
    Credentials represent the user, but that doesn't mean they carry login nor password. Some credentials do contain these, but others don't. Check this out: if you want to use Windows auth, your proxy must support it. – Simon Mourier Jul 23 '19 at 14:04
  • Then the MS documentation is a little misleading. How do I determine whether the credentials have the correct format? Unfortunately I'm not able to view the credentials on the client. Like stated in the question my proxy server (Squid) is configured to work with LDAP/AD, but I will check again, if there are additional configurations for supporting NTLM. – tg24 Jul 24 '19 at 07:10
  • See if any of these helps? https://github.com/dotnet/corefx/issues/25988, https://stackoverflow.com/questions/12212116/how-to-get-httpclient-to-pass-credentials-along-with-the-request – Tarun Lalwani Jul 25 '19 at 14:52
  • Unfortunately both doesn't help. I think the problem is the proxy server since even Internet Explorer ask for credentials. I need to check the configuration. – tg24 Jul 29 '19 at 05:57
  • @SimonMourier Even though my problem is not solved until now, if you would like to add an answer, I will give the bounty to you since your comments where leading me into the right direction. – tg24 Jul 29 '19 at 06:04
  • 1
    Thanks but I really didn't do much :-), in fact *you* just answer yourself if you found a way to make it work or found a workaround – Simon Mourier Jul 29 '19 at 16:43

1 Answers1

2

You have to define proxy and main URL in code.

var TARGETURL = "http://en.wikipedia.org/";

HttpClientHandler handler = new HttpClientHandler()
{
    Proxy = new WebProxy("http://127.0.0.1:8888"),
    UseProxy = true,
};

try this.

handler.Proxy.Credentials = CredentialCache.DefaultNetworkCredentials;
handler.Credentials = CredentialCache.DefaultNetworkCredentials;

ok so your webserivces uses windows authentication. Your desktop client is working under your credential you need impersonation https://learn.microsoft.com/en-us/dotnet/api/system.security.principal.windowsidentity.impersonate?view=netframework-4.8

check this if it works for you if it is basic authentication.

HttpClient client = new HttpClient(handler);

            **var byteArray = Encoding.ASCII.GetBytes("username:password1234");**


**client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Basic", Convert.ToBase64String(byteArray));**
Jin Thakur
  • 2,711
  • 18
  • 15
  • Both options `Proxy = new WebProxy("http://127.0.0.1:8888")` and `handler.Proxy = WebRequest.DefaultWebProxy;` do work when defining the credentials manually like you can see in my example above. I've checked the proxy log files to confirm this. When using `CredentialCache.DefaultNetworkCredentials` it doesn't, but I want it to. I think the problem is made while setting the credentials. – tg24 Jul 23 '19 at 06:22
  • check your application pool identity try changing that credentials to the new account. you can place credentials in web.config too. In my case Proxy = new WebProxy("http://127.0.0.1:8888") works handler.Proxy = WebRequest.DefaultWebProxy; does not worked. – Jin Thakur Jul 23 '19 at 16:58
  • try handler.Proxy.Credentials = CredentialCache.DefaultNetworkCredentials; handler.Credentials = CredentialCache.DefaultNetworkCredentials; – Jin Thakur Jul 23 '19 at 16:58
  • There's no IIS involved. Like stated in the question, I try to pass the Windows Authentication Credentials. – tg24 Jul 24 '19 at 06:20
  • if you want to run a desktop client you have to use impersonation https://learn.microsoft.com/en-us/dotnet/api/system.security.principal.windowsidentity.impersonate?view=netframework-4.8 – Jin Thakur Jul 24 '19 at 21:51
  • so you made a desktop webservice client and want to pass some other credentials or run under context of some other user. use impersonation. proxy is just for windows authentication to call another windows authentication process.https://learn.microsoft.com/en-us/dotnet/api/system.security.principal.windowsidentity.impersonate?view=netframework-4.8 – Jin Thakur Jul 24 '19 at 21:53
  • Please read my question. I want to authenticate against the proxy while using the current users login data. – tg24 Jul 29 '19 at 05:54
  • There are various ways If it is basic authntication it can work like this – Jin Thakur Jul 29 '19 at 18:46