I am trying to set up a WCF webservice with BasicHttpBinding and authentication using username/password. I made custom authentication class. However, it is never called (verified by debugging). This is my web.config:
<system.serviceModel>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
<behaviors>
<serviceBehaviors>
<behavior>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="Compareware_WebApp.webservices.AuthenticationValidator, Compareware_WebApp" />
</serviceCredentials>
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true" />
<serviceDebug includeExceptionDetailInFaults="false" />
</behavior>
</serviceBehaviors>
</behaviors>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding">
<security mode="TransportCredentialOnly">
<message clientCredentialType="UserName" />
</security>
</binding>
</basicHttpBinding>
</bindings>
<services>
<service name="Compareware_WebApp.webservices.Accounts">
<endpoint address="/webservices/Accounts.svc" binding="basicHttpBinding"
bindingConfiguration="BasicHttpBinding" name="BasicEndpoint"
contract="Compareware_WebApp.webservices.IAccounts" />
</service>
</services>
<client />
This is my authentication class:
namespace Compareware_WebApp.webservices
{
public class AuthenticationValidator : UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (null == userName || null == password)
{
throw new ArgumentNullException();
}
if (!Membership.ValidateUser(userName, password))
{
// This throws an informative fault to the client.
throw new FaultException("Unknown Username or Incorrect Password");
}
}
}
}
What am I doing wrong?
I am also stuck in this problem, and I got a solution. If you want to call the Validate
method of the UserNamePasswordValidator
you must use the TransportWithMessageCredential
security.
NOTE: You must host the WCF Services at the IIS server and have to enable SSL for your website, otherwise it will not work.
WCF Server Web.config file
<?xml version="1.0"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/>
</startup>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="wsHttp">
<security mode="TransportWithMessageCredential">
<message clientCredentialType="UserName"/>
</security>
</binding>
</wsHttpBinding>
</bindings>
<services>
<service name="TransportWithMessageCredential.Service1" behaviorConfiguration="wsHttpBehavior">
<endpoint address="" binding="wsHttpBinding" bindingConfiguration="wsHttp" contract="TransportWithMessageCredential.IService1">
<identity>
<dns value="localhost"/>
</identity>
</endpoint>
<host>
<baseAddresses>
<add baseAddress="https://localhost:8080/WCFDemo"/>
</baseAddresses>
</host>
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior name="wsHttpBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="true"/>
<serviceDebug includeExceptionDetailInFaults="false"/>
<serviceCredentials>
<userNameAuthentication userNamePasswordValidationMode="Custom" customUserNamePasswordValidatorType="TransportWithMessageCredential.ServiceAuthanticator, TransportWithMessageCredential"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
</system.serviceModel>
<system.web>
<compilation debug="true"/>
</system.web>
</configuration>
Service Authentication class
public class ServiceAuthanticator : UserNamePasswordValidator
{
/// <summary>
///
/// </summary>
/// <param name="userName"></param>
/// <param name="password"></param>
public override void Validate(string userName, string password)
{
if (String.IsNullOrEmpty(userName) || String.IsNullOrEmpty(password))
{
throw new FaultException("Please, Provide the username and password!!!");
}
if (userName != "abc" || password != "abc")
{
throw new FaultException("Sorry, Invalid username or password!!!");
}
}
}
WCF Client app.config file
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<system.serviceModel>
<bindings>
<wsHttpBinding>
<binding name="WSHttpBinding_IService1">
<security mode="TransportWithMessageCredential">
<transport clientCredentialType="None" />
<message clientCredentialType="UserName" />
</security>
</binding>
</wsHttpBinding>
</bindings>
<client>
<endpoint address="https://kalpesh-pc/WCFAuth/Service1.svc" binding="wsHttpBinding"
bindingConfiguration="WSHttpBinding_IService1" contract="ServiceReference1.IService1"
name="WSHttpBinding_IService1">
<identity>
<dns value="localhost" />
</identity>
</endpoint>
</client>
</system.serviceModel>
</configuration>
Client Program to call the WCF Services
try
{
Service1Client objClient = new Service1Client();
objClient.ClientCredentials.UserName.UserName = "abc";
objClient.ClientCredentials.UserName.Password = "abc";
objClient.Open();
string strData = objClient.GetData(10);
}
catch (FaultException ex)
{
Console.WriteLine(ex.Message);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
Console.ReadKey();
Happy Coding...
:)