Search code examples
c#.netwcfbasic-authenticationdotnet-httpclient

Consuming a WCF REST service with Basic authentication using HttpClient.GetAsync() results in (401) Unauthorized


I am trying to connect to a WCF self-hosted REST service with HttpClient using Basic authentication, but keep getting (401) unauthorized. When I access the same endpoint from a web browser, entering the same user name and password results in success. The authentication on service side is done via UserNamePasswordValidator. I am leaving the Validate method empty for testing purposes, so all the requests should be valid. Nonetheless calling GetAsync() results in (401) Unauthorized. When I set a breakpoint in the Validate method, I can check, that correct values are passed. Any explanation for this behavior?

The client

using (var httpClient = new HttpClient())
{
    var authString = "admin:admin";
    var authEncoded = Encoding.GetEncoding("ISO-8859-1").GetBytes(authString);
    var authBase64String = Convert.ToBase64String(authEncoded);
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", authBase64String);
    httpClient.BaseAddress = new Uri(UriFactory.GetServiceUrl());

    using (var response = await httpClient.GetAsync(serviceDomain))
    {
        string responseData = await response.Content.ReadAsStringAsync();
        return JsonConverter.FromJson<TResponse>(responseData);
    }
}

The service

public class CustomUserNameValidator : UserNamePasswordValidator
{
    public override void Validate(string userName, string password)
    {
    }
}

This is the service configuration

<system.serviceModel>
<bindings>  
  <webHttpBinding>  
    <binding name="HttpsBinding">  
      <security mode="Transport">  
        <transport clientCredentialType="Basic" />  
      </security>  
    </binding>  
  </webHttpBinding>  
</bindings>  

<services>
  <service behaviorConfiguration="MyServiceBeahvior" name="ServiceImplementation">
    <endpoint address="status"        binding="webHttpBinding" bindingConfiguration="HttpsBinding" contract="Status.IStatusService"            behaviorConfiguration="MyWebBahviorr"/>
    <endpoint address="mex"           binding="mexHttpsBinding" contract="IMetadataExchange" />
    <host>
      <baseAddresses />
    </host>
  </service>
</services>

<behaviors>
  <serviceBehaviors>
    <behavior name="MyServiceBeahvior">
      <serviceMetadata httpsGetEnabled="True" />
      <serviceDebug includeExceptionDetailInFaults="True" />
    </behavior>
  </serviceBehaviors>
  <endpointBehaviors>
    <behavior name="MyWebBahvior">
      <webHttp automaticFormatSelectionEnabled="false" />
    </behavior>
  </endpointBehaviors>
</behaviors>

_oServiceHost.Credentials.UserNameAuthentication.UserNamePasswordValidationMode = UserNamePasswordValidationMode.Custom;
_oServiceHost.Credentials.UserNameAuthentication.CustomUserNamePasswordValidator = new CustomUserNameValidator();

The communication is over HTTPS with a self-signed certificate.


Solution

  • Finally, I was able to find my problem using Fiddler. I was sending the request without the final slash (eg https://localhost:4444/status instead of https://localhost:4444/status/). The web browser was able to handle the redirect, but the HttpClient failed.