Friday, August 10, 2012

WCF: Username/Password Authentication using BasicHttpBinding


I was required to do this type of Authentication in one of my projects. I am documenting the steps that I did for future reference.

Create an X509 certificate

The username/password authentication requires the communication between the client and server to be encrypted.

A test certificate can be created using the Certificate Creation Tool (Makecert.exe) by Microsoft.
http://msdn.microsoft.com/en-us/library/bfsktky3(v=vs.80).aspx
  1. Open the Visual Studio command prompt
  2. Type the following command
Certificate Authority
makecert -n "CN=MMRootAuthority" -r -sv MMRootAuthority.pvk MMRootAuthority.cer
pvk2pfx -pvk MMRootAuthority.pvk -spc MMRootAuthority.cer -pfx MMRootAuthority.pfx -pi “YourPassword” -po “YourPassword”

Certificate Revocation List
makecert -crl -n "CN=MMRootCRL" -r -sv MMRootCRL.pvk MMRootCRL.crl
pvk2pfx  -pvk MMRootCRL.pvk -spc MMRootCRL.crl-pfx MMRootCRL.pfx -pi “YourPassword” -po “YourPassword”

Server Certificate
makecert -iv MMRootAuthority.pvk -n "CN=MMServerCertificate" -ic MMRootAuthority.cer -sr CURRENTUSER -ss My -sky exchange -eku 1.3.6.1.5.5.7.3.1 -pe  -sv MMServerCertificate.pvk MMServerCertificate.cer
pvk2pfx -pvk MMServerCertificate.pvk -spc MMServerCertificate.cer -pfx MMServerCertificate.pfx -pi “YourPassword” -po “YourPassword”

Client Certificate
makecert -iv MMRootAuthority.pvk -n "CN=MMClientCertificate" -ic MMRootAuthority.cer -sr CURRENTUSER -ss My -sky exchange -eku 1.3.6.1.5.5.7.3.2  -pe  -sv MMClientCertificate.pvk MMClientCertificate.cer
pvk2pfx -pvk MMClientCertificate.pvk -spc MMClientCertificate.cer -pfx MMClientCertificate.pfx -pi “YourPassword” -po “YourPassword”

Viewing certificates
If the command is successful, installed certificates can be viewed by
  1. Open command prompt, type in mmc and press enter.
  2. Select Add/Remove Snap-ins and select Certificates.

Configure IIS

The following article helps on how to enable SSL in IIS.
http://learn.iis.net/page.aspx/144/how-to-set-up-ssl-on-iis/



Here are the steps I did to enable SSL in IIS 
  1. Install the Root Certificate Authority in the Local Machine's Trusted Certificate Store. 
  2. Install the Server Certificate in the Local Machine's Personal Certificate Store. 
  3. Go to IIS and open web site properties/bindings, configure the port for SSL and the certificate to use.
Could not find base address that matches scheme https for the endpoint with binding MetadataexchangeHttpsBinding. Registered base address schemes are [http]

When running from inside Visual Studio, the likely culprit is the project not being configured to use the local IIS Web Server.


Ensure that the service is configured to use the local IIS Web Server under project properties/web tab.

Configure the Username/Password Authentication

I used the following steps to configure username/password authentication
  1. Navigate to configuration/system.serviceModel/bindings/basicHttpBinding/
  2. Add the following lines
    <binding name="usernameHttps">
       <security mode="TransportWithMessageCredential">
          <message clientCredentialType="UserName"/>                   
       </security>                   
    </binding>
  3. Change your endpoint to use the usernameHttps binding
    <endpoint binding="basicHttpBinding"
       bindingConfiguration="usernameHttps" name="BasicHttpEndpoint" contract="WcfService4.IService1" >   
    </endpoint>
    The mexHttpBinding will need to be changed to mexHttpsBinding
    The httpGetEnabled will need to be changed to httpsGetEnabled

  4. Implement a username/password validator by creating a class that inherits from UserNamePasswordValidator
    public class UsernNamePasswordValidator : UserNamePasswordValidator {
        public override void Validate(string userName, string password) {}}
    Ensure that System.IdentityModel and System.IdentityModel.Selectors are referenced.
  5. In the web.config file, goto to configuration/system.serviceModel/behaviors/serviceBehaviors/behavior
  6. Add the following line
    <userNameAuthentication userNamePasswordValidationMode="Custom"
    customUserNamePasswordValidatorType="WcfService4.UserNamePasswordValidator, WcfService4"/>

    The first parameter is the fully qualified name of the custom username/password validator class.
    The second parameter specifies the name of the assembly that the validator is located in.

To audit login attempts a serviceSecurityAudit node can be added
http://msdn.microsoft.com/en-us/library/ms731694.aspx


I used the following configuration.
<serviceSecurityAudit
auditLogLocation="Application"
serviceAuthorizationAuditLevel="Failure"

messageAuthenticationAuditLevel="Failure"
suppressAuditFailure="true" />

When security related problems are encountered, this setting will write to the event log of the machine where the service is hosted.

My web.config file

This is my web.config file with unrelevant sections ommitted
<?xml version="1.0"?>
<configuration>
  <system.serviceModel>   
    <bindings>           
      <basicHttpBinding>     
        <binding name="usernameHttps">
          <security mode="TransportWithMessageCredential">
            <message clientCredentialType="UserName"/>                   
          </security>                   
        </binding>
      </basicHttpBinding>
    </bindings>   
    <services>                 
      <service name="WcfService4.Service1" behaviorConfiguration="DefaultBehavior">       
        <endpoint binding="basicHttpBinding"
          bindingConfiguration="usernameHttps" name="BasicHttpEndpoint" contract="WcfService4.IService1" >   
        </endpoint>
      </service>     
    </services>
    <behaviors>
      <serviceBehaviors>
        <behavior name="DefaultBehavior">
          <serviceCredentials>
            <userNameAuthentication userNamePasswordValidationMode="Custom"
             customUserNamePasswordValidatorType="WcfService4.CustomUserNameValidator, WcfService4"/>
          </serviceCredentials>
        </behavior>         
      </serviceBehaviors>     
    </behaviors>       
  </system.serviceModel> 
</configuration>

I'll be creating an article on how to consume this service in my next post.

No comments:

Post a Comment