0
votes

I am wondering if in .NET, if it possible to send over the credentials of the identity running an application pool in IIS to an API that uses Basic Auth. I have successfully been able to retrieve the identity context from the application pool. However, in every example i see for using Basic Auth. They all seem to require to manually add the Authorization header to the request. This is a problem since i do not directly have access to the password of the windows identity thus i can't manually create the Basic Auth Token. I have been trying to use the .DefaultCredentials property but it fails to generate the Auth header thus the response fails with 401. If this isn't possible then i'll take a different approach but wanted to make sure before i do so. The full code sample is below...i have tried multiple ways but all end up with the same 401.

            using (var impersonationContext = WindowsIdentity.Impersonate(IntPtr.Zero))
        {
            HttpWebRequest request1 = (HttpWebRequest)WebRequest.Create("url");
            HttpClient request2 = new HttpClient();
            WebClient request3 = new WebClient();
            WebRequest request4 = WebRequest.Create("url");

            try
            {
                // this code is now using the application pool indentity
                try
                {
                    //Method 1
                    //request1.UseDefaultCredentials = true;
                    //request1.PreAuthenticate = true;
                    //string encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(WindowsIdentity.GetCurrent().Name + ":" + "No password :("));
                    //request1.Headers.Add("Authorization", "Basic " + WindowsIdentity.GetCurrent().Token.ToString());
                    //HttpWebResponse response = (HttpWebResponse)request1.GetResponse();
                    //using (var reader = new StreamReader(response.GetResponseStream()))
                    //{
                    //    JavaScriptSerializer js = new JavaScriptSerializer();
                    //    var objText = reader.ReadToEnd();
                    //    Debug.WriteLine(objText.ToString());
                    //}

                    ////Method 2
                    //client.DefaultRequestHeaders.Accept.Clear();
                    //client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
                    //client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", WindowsIdentity.GetCurrent().Token.ToString());
                    //HttpResponseMessage response2 = client.GetAsync("url").Result; //.Result forces sync instead of async.
                    //var result = response2.Content.ReadAsStringAsync().Result;
                    //Debug.WriteLine(result);

                    //Method 3
                    //client2.Credentials = CredentialCache.DefaultNetworkCredentials;
                    //var result2 = client2.DownloadString("url");
                    //Debug.WriteLine(result2);

                    //Method 4
                    //request4.Credentials = CredentialCache.DefaultCredentials;
                    //string result4;
                    //using (var sr = new StreamReader(request4.GetResponse().GetResponseStream()))
                    //{
                    //    result4 = sr.ReadToEnd();
                    //}
                    //Debug.WriteLine(result4);
                }
                catch (Exception ex)
                {
                    throw new Exception("API Call Failed: " + ex.ToString() + " for " + WindowsIdentity.GetCurrent().Name + " request: " + request4.Headers.ToString());
                }
            }
            finally
            {
                if (impersonationContext != null)
                {
                    impersonationContext.Undo();
                }
            }
1
This seems to have a lot of info that sounds like what you're wanting stackoverflow.com/questions/12212116/…Charles Paske
After updating the code to their use case, it still received a 401. I inspected the headers for the request and the authorization header was still being left out which is why it fails.user1732364
Are you restricted to Basic Auth? Perhaps NTLM might work as long as the API calls were in the same thread the application was running in (httpclient vs webclient)?Charles Paske

1 Answers

0
votes

App Pool Identity and Basic Auth serves two different purpose and I suggest not to mix those. As you also mentioned that you don't know the password of app pool identity and it's self explanatory. App pool identity also allows the API's to access system resources for example, accessing a file share.

Whereas Basic Auth allows you to secure your API as a whole from being wide open and anyone accessing it. Except the ones who knows UserName:Password which needs to be passed with each HttpRequest (containing HttpHeader with UserName:Password in Base64).

Considering these facts, when API developer needs to share UserName and Password with all the parties, it's advisable not to share App Pool Identity credentials.

I have worked with both App Pool Identity and Basic Auth and I recommend to keep these separate.