none
Logon error on ASP.NET Webservice RRS feed

  • Question

  • Hi everybody.

    I'm a little bit confused about a problem which i don't understand, why it happens.

    I have two Webservices (ASP.NET Web Api)
    on same Server, 
    on same IIS,
    with same IP (different CNAME's to same IP),
    with different Sites in IIS.

    Webservice One (WS1)

    • Applicationpool => WS1Pool  (Integrated, V4.0)
    • ServiceUser => DOMAIN\\WS1_Service
    • Authenticationmode => Windows (Rest disabled)
    • Authorization Roles => Allow All Users

    Webservice Two (WS2)

    • Applicationpool => WS2Pool (Integrated, V4.0)
    • ServiceUser => DOMAIN\\WS2_Service
    • Authenticationmode => Windows (Rest disabled)
    • Authorization Roles => Allow All Users

    Both Serviceuser are local Administrators.

    My Problem:

    WS2 call a WebApi Method of WS1 with his Network Credentials (WS2_service).
    This worked now over a Year without any problems. But since this Week it's not working any longer.
    I get now always a 401 Forbidden HttpError.

    Here the Eventlog Error From ServerSecurity Error Log Entry

    I changed nothing on Code, and nothing on Permissions of this Serviceuser's.
    I checked all Database Permissions.
    I checked all Settings on both IIS Services.

    Someone can help me, thanks.

    System Details:

    • IIS Version 8.5.9600.16384
    • Windows Server 2012 R2
    • .NET Framework 4.6 (Server 1) 4.7 (Server2)

    • Edited by Osti89 Tuesday, November 14, 2017 2:10 PM Add Localadministrator Info
    Tuesday, November 14, 2017 1:36 PM

Answers

All replies

  • So the 401 could be thrown on a resource that you have not listed, like an O/S resource, as an example.

    Do you know where in the code the 401 is being thrown?

    It seems to me that you need to be using Fiddler and looking the raw HTML at the time of the 401.

    Tuesday, November 14, 2017 3:36 PM
  • Hello, thanks for your fast answer.

    Yes i know where the Exception is thrown.
    WS2 call in different situations, 3 different Methods from WS1.
    And each return Forbidden Exception.

    I have the Forbidden Page in Errorlog (Reponse-Content)
    WebservicveCallFromServer


    And when i call the Same Methods from WS1 (with same parameters and with same Serviceuser like WS2)
    but this from another COmputer (Example my Devops PC)
    Then is successfull.

    CallWebserviceFromOtherComputer

    Tuesday, November 14, 2017 4:16 PM
  • Hi Osti,

    >>but this from another COmputer (Example my Devops PC)

    It seems if you call WS1 from another computer with DOMAIN\\WS2_Service, it works. I suggest you make a test that calling WS1 from the same computer with DOMAIN\\WS2_Service, will it work?

    To check whether it is related with Windows Auth, I suggest you enable Anonymous Authentication, will it work if you call WS1 from WS2?

    To check whether it is related with DOMAIN\\WS2_Service account, I suggest you create a new ServiceUser account with related permission, will it work?

    Have you recently changed the DOMAIN\\WS2_Service password? I suggest you restart IIS to make a try.

    Best Regards,

    Edward


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Wednesday, November 15, 2017 1:55 AM
  • Hi Edward

    Thanks you for your Anwser.

    I called WS1 with DOMAIN\\WS2_Service and this still not work. 
    It dont work from Service to Service and it don't work directly in IE.

    I tryed with disabled WinAuth. and with Anonymous instead. And this works. The Service can call WS1 now, but for some functions i need the Current User of HttpContext. (This still work?)

    I tried also with my DevOp Account, Adminaccount and Serviceuser. No one are able to connect from WS2 to WS1.

    I have resetted the Password an give a new one, => don't work.

    I have restarted the Full Server already, and now i restarted IIS, => don't work.

    Thanks and best regards

    Thursday, November 16, 2017 6:46 AM
  • Hi,

    If you create a new web service with WindowAuth, and call it from WS2_Service, will it work?

    Best Regards,

    Edward


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Thursday, November 16, 2017 6:52 AM
  • Hi Edward,

    Nope it don't works.

    It don't works directly over Internet Explorer, either.

    On different servers it works, but on same servers it don't work.

    Monday, November 20, 2017 3:37 PM
  • Hi Osti,

    This is an interesting result. In general, we hit issue that the service works from the same server but failed from different server. Your scenario is opposite.

    Could you share us a simple solution with two Service Project, and detail steps to configure the sites in IIS? I will try to follow your steps step by step to try to reproduce your issue. From the whole description, I fail to find the root caused.

    Best Regards,

    Edward


    MSDN Community Support
    Please remember to click "Mark as Answer" the responses that resolved your issue, and to click "Unmark as Answer" if not. This can be beneficial to other community members reading this thread. If you have any compliments or complaints to MSDN Support, feel free to contact MSDNFSF@microsoft.com.

    Tuesday, November 21, 2017 2:25 AM
  • Hi Edward

    I have make two Webapi Services, one which call the others.

    Testobject:

    public class Component
        {
    
            public string ComponentName { get; set; }
            public string ComponentNumber { get; set; }
            public int Flashpoint { get; set; }
        }

    Added code below on both WebapiConfig:

    public static class WebApiConfig
        {
            public static void Register(HttpConfiguration config)
            {
                // Web API configuration and services
    
                // Web API routes
                config.MapHttpAttributeRoutes();
    
                config.Routes.MapHttpRoute(
                    name: "DefaultApi",
                    routeTemplate: "api/{controller}/{id}",
                    defaults: new { id = RouteParameter.Optional }
                );
    
                config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("text/html")); // default return type to json
                config.Formatters.JsonFormatter.SupportedMediaTypes.Add(new MediaTypeHeaderValue("application/x-www-form-urlencoded"));
    
                config.Formatters.JsonFormatter.SerializerSettings.Formatting = Formatting.None;
                config.Formatters.JsonFormatter.SerializerSettings.PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.All; // enable cyclic references
                config.Formatters.JsonFormatter.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;
    
                config.Formatters.Remove(config.Formatters.XmlFormatter);
                config.Formatters.Remove(config.Formatters.FormUrlEncodedFormatter);
                var jqueryFormatter = config.Formatters.FirstOrDefault(x => x.GetType() == typeof(JQueryMvcFormUrlEncodedFormatter));
                config.Formatters.Remove(jqueryFormatter);
    
                config.Formatters.JsonFormatter.SerializerSettings.Converters.Add(new IsoDateTimeConverter());
                config.Formatters.JsonFormatter.SerializerSettings.Culture = new System.Globalization.CultureInfo(string.Empty) { NumberFormat = new System.Globalization.NumberFormatInfo() { NumberDecimalDigits = 4, NumberGroupSeparator = "." } }; // Decimal Configuration
            }
        }



    Code below is the ComponentController of Webservice 1 with Dummydata:

    namespace TestWebservice1.Controllers
    {
        public class ComponentController : ApiController
        {
            // GET: api/Component
            public async Task<IHttpActionResult> Get()
            {
    
                try
                {
                    var components = await CreateComponents();
    
                    return Ok(components);
                }
                catch (Exception e)
                {
    
                    return Content(HttpStatusCode.InternalServerError, e.Message);
                }
            }
    
            private Task<List<Component>> CreateComponents()
            {
                var components = new List<Component>();
    
                var random = new Random();
                var count = random.Next(10, 50);
    
                for (int i = 0; i < count; i++)
                {
                    var component = new Component();
                    component.ComponentNumber = Generator.RandomComponentNumber();
                    component.ComponentName = Generator.RandomComponentName();
                    component.Flashpoint = Generator.RandomFlashpoint();
                    components.Add(component);
                }
                return Task.FromResult(components);
    
            }
    
        }
    }

    Code below is the ComponentController of Webservice 2 which calls Webservice 1:

    namespace TestWebservice2.Controllers
    {
        public class ComponentController : ApiController
        {
    
            private readonly string LocalPath = "http://localhost:57902/api/component";
            private readonly string ServerPath = "http://webservice1.domain.local:12444/api/component";
    
    
            public async Task<IHttpActionResult> Get()
            {
    
                try
                {
                    var components = await SimpleHttpClient.Get<List<Component>>(ServerPath);
    
                    return Ok(components);
                }
                catch (Exception e)
                {
                    var responseException = e as HttpResponseException;
                    if (responseException != null)
                    {
                        return Content(HttpStatusCode.InternalServerError, responseException.Message+SimpleHttpClient.GetResponseMessage(responseException.Response));
                    }
                    return Content(HttpStatusCode.InternalServerError, e.Message);
                }
            }
    
    
        }
    }
    

    SimpleHttpClient which is used to get data from other webservice:

    namespace TestWebservice2.Helper
    {
        public static class SimpleHttpClient
        {
    
            private static HttpClientHandler GetClientHandler()
            {
                return new HttpClientHandler() { AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate, UseDefaultCredentials = true };
            }
    
            public static async Task<T> Get<T>(string uri, int timeout = 30)
            {
                using (HttpClient client = new HttpClient(GetClientHandler()))
                {
                    client.Timeout = TimeSpan.FromSeconds(timeout);
                    var response = await client.GetAsync(uri).ConfigureAwait(false);
                    if (response.IsSuccessStatusCode)
                    {
                        return await response.Content.ReadAsAsync<T>().ConfigureAwait(false);
                    }
                    else
                    {
                        throw await GetHttpExceptionAsync(response);
                    }
                }
            }
    
            private static Task<HttpResponseException> GetHttpExceptionAsync(HttpResponseMessage response)
            {
                return Task.FromResult(new HttpResponseException(response));
            }
    
    
            public static string GetResponseMessage(this HttpResponseMessage response)
            {
                try
                {
                    return response.Content.ReadAsStringAsync().WaitAndUnwrapException();
                }
                catch (Exception e)
                {
                    Debug.WriteLine(e.Message);
                }
                return null;
            }
    
    
        }
    }

    IIS Settings

    After creating the Website in IIS i made the following changes.

    First Try:

    • New Website "TestWebservice1" with (DefaultAppPool)
      => Authentication Windows Enabled and Anonymous Disabled
      => Binding Hostname: webservice1.domain.local:12444 (Server IP Adress)
    • New Website "TestWebservice2" with (DefaultAppPool)
      => Authentication Windows Enabled and Anonymous Disabled
      => Binding Hostname: webservice2.domain.local:12445 (Server IP Adress)

    Second Try:

    Changed AppPool of TestWebservice1 to AppPool of other Service "WS1" with Serviceuser
    Changed AppPool of TestWebservice2 to AppPool of other Service "WS2" with Serviceuser

    Both variants was not working (HTTP Error 401.1 - Unauthorized)

    Thanks for your help.

    Tuesday, November 21, 2017 12:25 PM
  • Hello

    I found a Info and a Workarround to fix this issue.

    https://www.epinova.no/en/blog/iis-loopback-problem-when-using-windows-authentication/

    I tryed now Method1 of this and it works now again.

    All Services can connect to the others.

    But i don't understand why this happens and why it works for over one year without any problems.
    And i also not understand why it's a Permission Denied Error and not a Host not found or something.

    I thanks to all for Help

    • Marked as answer by Osti89 Tuesday, November 21, 2017 2:46 PM
    Tuesday, November 21, 2017 2:46 PM