8

My backend is an ASPNet WebApi2 running under IIS and uses Windows Authentification.

I have 2 clients:

  1. WinForms: Passing the credentials is simple. I do the following:

        var credentialCache = new CredentialCache();
        credentialCache.Add(new Uri(uri.GetLeftPart(UriPartial.Authority)), "NTLM", credentials);
    
        WebRequestHandler handler = new WebRequestHandler()
        {
            AuthenticationLevel = AuthenticationLevel.MutualAuthRequested,
            Credentials = credentialCache,
            PreAuthenticate = true,
            UseDefaultCredentials = false
        };
    
        client = new HttpClient(handler, true)
        {
            BaseAddress = uri,
        };
    
  2. Angular: As the end-user will access the WebApi backend using the Angular app from non-Windows systems, how can I pass his/her windows credentials? (I have a login screen where the user must enter his domain/name and password).

I would like to pass the user credentials through code. Something like typed_rest-client. Unfortunately this lib is causing build errors and cannot be used.

Ivan-Mark Debono
  • 15,500
  • 29
  • 132
  • 263
  • Does this help https://spikesapps.wordpress.com/2017/08/04/how-to-implement-windows-authentication-in-an-angular-4-3-1-application-with-a-stand-alone-web-api/ ? – Tarun Lalwani May 06 '18 at 16:38
  • @TarunLalwani Unforturnately not. I want to pass the user credentials through code. – Ivan-Mark Debono May 08 '18 at 15:44
  • Does this relate? https://stackoverflow.com/questions/6748050/authenticate-windows-authentication-using-javascript – ForestG May 09 '18 at 12:34
  • 1
    Passing username and password is not usual when talking about windows authentication. A windows client will use ntlm or kerberos. If you pass un/pwd nithing will happen. I needed the same and I wrote an owin midleware that transforms basic auth header into windows identity by logging in the user on the server side side, with the lowest overhead possible. This allows any client that can add the basic auth header to pass credentials - including rhe browser or an ajax call. Could this help you? – ZorgoZ May 12 '18 at 19:13
  • 1
    On a Windows client, UseDefaultCredentials will trigger negotiate, resulting in either ntlm or kerberos. It wont pass username and password. You could use https://github.com/erlandranvinge/ntlm.js/ to emulate the ntlm handshake - but not kerberos, as that involves a third party. This is an other option. In Katana you cant have ntlm and basic auth in the same pipeline, but IIS handles this, thus you could use both my middleware for the angular client and ntlm for the windows client. – ZorgoZ May 12 '18 at 19:57
  • Actually, IIS can provide fallback to basic auth if ntlm fails. You could try to add the basic auth header up front. Could work without any extra middleware. But remember, that I am talking about basic auth, not form auth. So it will work with ajax calls, but not directly. My middleware can be easily transformed to handle form type authentication instead of basic. If you dont want to send credentials for all requests (as you do in the Windows client) you will have to combine with cookie based one. – ZorgoZ May 12 '18 at 19:57
  • Sending basic auth and letting the server do ntlm auth should too. I will send the credentials with every request. – Ivan-Mark Debono May 13 '18 at 01:38

1 Answers1

1

Here you can find the library: https://github.com/zorgoz/Http.BasicWindowsAuthentication

Note: it is not "released" yet, and it was designed and tested with self-host, not IIS integration, and never thought about having multiple authentication methods in parallel. Still, it could work even without modification.

As mentioned in the comments you could try using only IIS. Even if only Windows authentications is enabled and basic is not, if ntlm/keberos fails, it will fall back to some sort of basic. A browser would display the login dialog. And if you pass username and password, it will authenticate as it would be regular Windows authentication. As I said, you could add proper header up front in your ajax request, then you should not see the challenge. More here. The above mechanism should work transparently - although I never tried it.

If you want to use my middleware, you have to decide where to put it in the pipeline. Use UseStageMarker for that (more here). You will notice, that the middleware can provide feedback on the cause of a login failure. If you want it will add two header entries in the response, which you can inspect and display to the user in your Angular client.

ZorgoZ
  • 2,974
  • 1
  • 12
  • 34