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.
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.