There are several examples on the internet that focus on implementing a custom username password validator for a WCF service. Most of those samples are written using self-hosted applications and work as designed. There is a problem however when the same approach needs to be implemented using an IIS hosted site with Basic authentication enabled. If you have implemented a custom user name password validator for non-windows credentials and with the following settings:
<basicHttpBinding>
<binding name="basicHttp" closeTimeout="00:01:00" openTimeout="00:01:00"/>
<security mode="TransportCredentialOnly">
<transport clientCredentialType="Basic" proxyCredentialType="None" realm="" />
</security>
</binding>
</basicHttpBinding>
You probably came across this error:
The HTTP request is unauthorized with client authentication scheme 'Basic'. The authentication header received from the server was 'Negotiate,NTLM,Basic realm="localhost"'
This error indicates that the user credentials provided on the request are not valid for this realm (localhost). IIS is expecting to get a user that it can find on the local machine or domain. If you provide an existent local or active directory credential, the error will no longer be raised. However, you probably did not want to add Windows accounts for your custom authentication in the first place. In addition, even if you are using a local account, you can notice that the custom validator Validate method is never called. This is expected because IIS has already done the validation.
To get this to work on IIS, you can try the following settings:
<basicHttpBinding>
<binding name="basicHttp" closeTimeout="00:01:00" openTimeout="00:01:00"/>
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName" algorithmSuite="Default" />
</security>
</binding>
</basicHttpBinding>
We are changing the security mode to use transport with message credential which expects a message credential type. We set the credential type to UserName. This setting however requires for you to install a certificate on your local IIS and use HTTPS instead of HTTP, so make sure to change the endpoint address in both client and server config files to use HTTPS. For your development environment a Self-Signed certificate will be sufficient.
I hope this small article is able to help.