For implementation of WCF message security using certificates, Pl refer this post
--------------------------------------------------------------------------------------------------------
Implementation of WCF
transport security using self-signed certificates
Transport layer security means using HTTPS protocol (SSL).
This will make sure that the HTTP packets travel encrypted through the network.
With the below configuration, you will get confidentiality (because of
encryption) but YOU ARE NOT AUTHENTICATING the client. Any client can
successfully call https://subhasissecureservice.com/Service1.svc
as long as the client has the RootCA under its trusted roots folder. (which is
generally the case. In an internet-facing scenario, the SSLs are procured from
– say – Verisign. All clients PCs have Verisign in their trusted roots folder.)
Note – Transport security are for POINT-TO-POINT, while
Message security are for END-TO-END. (Think about it).
Creation
of SSL certificate for subhasissecureservice.com (exactly as any other cert)
makecert -n
"CN=SubhasisSecureService.com" -ic "SubhasisCA.cer" -iv
"SubhasisCAPrivateKey.pvk" -a sha1 -sky exchange -pe -sv
"SubhasisSecureServicePrivateKey.pvk"
"SubhasisSecureService_SSL.cer"
---private key password of the above is
secureservicepvtkeypwd
pvk2pfx -pvk
"SubhasisSecureServicePrivateKey.pvk" -spc
"SubhasisSecureService_SSL.cer" -pfx
"SubhasisSecureService_SSL.pfx" -pi secureservicepvtkeypwd
1.
Install the pfx in the server mmc.
2.
Make sure Root CA is in the server mmc (if not
procured/purchased).
3.
Update host file with <IP> tab SubhasisSecureService.com
(if DNS server is not used)
4.
Configure IIS to use site/webservice with SSL
(edit bindings).
5.
Make sure Root CA is in the client mmc (if not
procured/purchased).
6.
Update host file with <IP> tab SubhasisSecureService.com
in the client as well. (if DNS server is not used)
Server config file
(Note basicHttpBinding is used with SSL certificates)
Key sections
with yellow highlight
<system.serviceModel>
<client />
<services>
<service name="CertSecurityDemoService.Service1">
<endpoint address="" binding="basicHttpBinding" bindingConfiguration="secureBasicHttpBinding" contract="CertSecurityDemoService.IService1" />
</service>
</services>
<behaviors>
<serviceBehaviors>
<behavior>
<!--
To avoid disclosing metadata information, set the values below to false before
deployment -->
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="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="false"/>
</behavior>
</serviceBehaviors>
</behaviors>
<protocolMapping>
<add binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<bindings>
<basicHttpBinding>
<binding name="secureBasicHttpBinding" sendTimeout="00:10:00" receiveTimeout="00:10:00" openTimeout="00:10:00" closeTimeout="00:10:00">
<security mode="Transport">
<transport clientCredentialType="None"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<serviceHostingEnvironment aspNetCompatibilityEnabled="true" multipleSiteBindingsEnabled="true" />
</system.serviceModel>
Client config file
(Simple)
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService1">
<security mode="Transport" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://subhasissecureservice.com/Service1.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1"
contract="ServiceReference1.IService1" name="BasicHttpBinding_IService1" />
</client>
</system.serviceModel>
Note – In the above config, we have clientCredentialType as
“None”, which means we don’t expect to authenticate. Any client can consume the
webservice.
The purpose here is to prevent “man-in-the-middle” attack.
(i.e. Tampering of message)
--------------------------------------------------------------------------------------------------------
If you want to add additional security like custom
username/pwd, certificates etc to validate the client (prevent anonymous
access), along with transport layer security (HTTPS), You can do that by
slightly modifying the above code –
1)
At the service level, change security mode to “TransportWithMessageCredential” from
“Transport” (Note – TransportWithMessageCredential has high overhead) and add <message
clientCredentialType="UserName"/>
2)
Add a servicebehavior to custom validate the
username/password.
3)
Client config has minimal change. Only
securitymode is changed to TransportWithMessageCredential.
4)
Client code should pass the username and
password as shown below –
ServiceReference1.Service1Client cl = new ServiceReference1.Service1Client();
cl.ClientCredentials.UserName.UserName = "subhasisrout";
cl.ClientCredentials.UserName.Password = "abcxyz!$@#";
Console.WriteLine(cl.GetData(5));
Server config
<system.serviceModel>
<behaviors>
<serviceBehaviors>
<behavior
name="usernamevalidatebehavior">
<!--
To avoid disclosing metadata information, set the values below to false before
deployment -->
<serviceMetadata httpGetEnabled="true"
httpsGetEnabled="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="false"/>
<serviceCredentials>
<userNameAuthentication
customUserNamePasswordValidatorType="CertSecurityDemoService.CustomUserNameValidator,
CertSecurityDemoService"
userNamePasswordValidationMode="Custom"/>
</serviceCredentials>
</behavior>
</serviceBehaviors>
</behaviors>
<client/>
<services>
<service
name="CertSecurityDemoService.Service1"
behaviorConfiguration="usernamevalidatebehavior">
<endpoint address="" binding="basicHttpBinding"
bindingConfiguration="secureBasicHttpBinding" contract="CertSecurityDemoService.IService1"
/>
</service>
</services>
<protocolMapping>
<add
binding="basicHttpsBinding" scheme="https" />
</protocolMapping>
<bindings>
<basicHttpBinding>
<binding
name="secureBasicHttpBinding" sendTimeout="00:10:00"
receiveTimeout="00:10:00" openTimeout="00:10:00"
closeTimeout="00:10:00">
<security
mode="TransportWithMessageCredential">
<message
clientCredentialType="UserName"/>
</security>
</binding>
</basicHttpBinding>
</bindings>
<serviceHostingEnvironment
aspNetCompatibilityEnabled="true"
multipleSiteBindingsEnabled="true" />
</system.serviceModel>
--------------------------------------------------------------------------------------------------------
public class CustomUserNameValidator : System.IdentityModel.Selectors.UserNamePasswordValidator
{
public override void Validate(string userName, string password)
{
if (userName == null || password == null)
{
throw new ArgumentNullException();
}
if (!(userName == "subhasisrout" && password == "abcxyz!$@#"))
{
throw new System.IdentityModel.Tokens.SecurityTokenException("Bad Username or Password");
}
}
}
--------------------------------------------------------------------------------------------------------
Client
Web config
<system.serviceModel>
<bindings>
<basicHttpBinding>
<binding name="BasicHttpBinding_IService1">
<security mode="TransportWithMessageCredential" />
</binding>
</basicHttpBinding>
</bindings>
<client>
<endpoint address="https://subhasissecureservice.com/Service1.svc"
binding="basicHttpBinding" bindingConfiguration="BasicHttpBinding_IService1"
contract="ServiceReference1.IService1" name="BasicHttpBinding_IService1" />
</client>
</system.serviceModel>
--------------------------------------------------------------------------------------------------------
IIS
Settings
Anonymous Authentication – Enabled
Basic Authentication – Enabled
Everything else – Disabled