Reputation: 437
I have been trying to get this working for hours now and have not had any luck. I am trying to create a WCF web service that has validation. I want the consumer of the service to be required to do:
ServiceReference1.XServiceClient client = new ServiceReference1.XServiceClient();
client.ClientCredentials.UserName.UserName = "username";
client.ClientCredentials.UserName.Password = "password";
before he can call any of the service methods. I found out that I have to create a CustomUserNamePasswordValidator so I created class library project in the solution to contain the Custom Validator class. I just wanted to verify that it works.
namespace XServices
{
public class CustomUserNameValidator : UserNamePasswordValidator
{
public override void Validate(string username, string password)
{
if (!(username == "test" && password == "password"))
{
throw new FaultException("Invalid username or password!");
}
}
}
}
Then I tried to make the necessary changes to my web.config file in the WCF project to support it. Unfortunately, this is where I had my first trouble.
Here is my web.config file as it is now.
<?xml version="1.0"?>
<configuration>
<connectionStrings>
<!-- connection strings ommitted for security reasons -->
</connectionStrings>
<system.web>
<compilation debug="true" targetFramework="4.0" />
<customErrors mode="Off"/>
</system.web>
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior>
<!-- To avoid disclosing metadata information, set the value below to false and remove the metadata endpoint above before deployment -->
<serviceMetadata httpGetEnabled="true" />
<!-- To receive exception details in faults for debugging purposes, set the value below to true. Set to false before deployment to avoid disclosing exception information -->
<serviceDebug includeExceptionDetailInFaults="true"/>
</behavior>
<behavior name="CustomValidator">
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="CustomUserNameValidator.XServices.CustomUserNameValidator, CustomUserNameValidator"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<wsHttpBinding>
<binding name="Binding1">
<security mode="Message">
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<serviceHostingEnvironment multipleSiteBindingsEnabled="true" />
</system.serviceModel>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
</system.webServer>
</configuration>
The MSDN docs are very unclear on how the customUserNamePasswordValidatorType works. The example https://msdn.microsoft.com/en-us/library/aa702565(v=vs.110).aspx completely glosses over it so I have no idea if I even did it correctly. And worse, it does not throw an error if what you put for that parameter is incorrect. It just silently ignores it. Long story short, the Validate method of my custom validator is not being called. I can't figure out why and I haven't found anything that has worked after hours of google searching. Please help.
Upvotes: 0
Views: 399
Reputation: 3959
In your service config, you forgot to associate the serviceBehavior with your service. Therefore your service don't know anything about your custom validator.
The following section is missing:
<services>
<service behaviorConfiguration="CustomValidator" name="ServiceName...">
<endpoint name="EndpointName..." bindingConfiguration="Binding1" address="..." binding="wsHttpBinding" contract="..." />
</service>
</services>
Upvotes: 1