Step by Step Guide for Authenticating WCF Service with Username and Password over SSL

Step by Step Guide for Authenticating WCF Service with Username and Password over SSL Edit


Here is a short step by step guide on how to get your WCF service to perform Message and Transport level security over SSL with user name and password. I ran into this recently and thought should document it along with source code to provide reference for the rest of us.

1. If your development machine is XP (or 2K3 server) and you need dev SSL cert installed on it, follow the instructions mentioned in the articles here. The SelfSSL makes it real easy to do self signed certificates, literally one statement.

2. Create a WCF Service Project. Name the service and contracts appropriately. In my sample it is a simple contract like follows.

1 [ServiceContract]
2  public interface IWcfService
3  {
4      [OperationContract]
5      string GetData(int value);
6  }

Make sure you make the appropriate config changes matching with your service contract.

2. Add a custom validator class in your service. You can create a separate file for it. In this example I have added it to the main service file WcfService.svc.cs. You are going to need to add the reference (not just adding these lines at the top, go to add-reference and add the corresponding dll’s to the project)

using System.IdentityModel.Selectors;
using System.IdentityModel.Tokens;

and the custom validator code.

01 public class CustomValidator : UserNamePasswordValidator
02     {
03         public override void Validate(string userName, string password)
04         {
05             if (userName == "test" && password == "test")
06                 return;
07             throw new SecurityTokenException(
08                 "Unknown Username or Password");
09         }
10     }

You probably want to make this user name and password moved to a more secure location or point to your database/authentication store for security and maintainability perspective.

3. Now the code part is done. Move to config file. Enable custom errors so you know details about the errors happening.

<customErrors mode=”Off” defaultRedirect=”GenericErrorPage.htm”>

4. Add a new bindings attribute in the config called SafeServiceConf which will specify the TransportWithMessageCredential type of security. You can add this right before </system.serviceModel>

01 <bindings>
02 <wsHttpBinding>
03 <binding name="SafeServiceConf" maxReceivedMessageSize="65536">
04 <readerQuotas maxStringContentLength="65536" maxArrayLength="65536"
05 maxBytesPerRead="65536" />
06 <security mode="TransportWithMessageCredential">
07 <message clientCredentialType="UserName" />
08 </security>
09 </binding>
10 </wsHttpBinding>
11 </bindings>
12 <bindings>       <wsHttpBinding>          <binding name="SafeServiceConf"maxReceivedMessageSize="65536">             <readerQuotas maxStringContentLength="65536" maxArrayLength="65536"                maxBytesPerRead="65536" />             <security mode="TransportWithMessageCredential">                <message clientCredentialType="UserName" />             </security>          </binding>       </wsHttpBinding>    </bindings>

5. Modify your end point address to refer to this binding configuration

1 <endpoint address="" binding="wsHttpBinding" contract="MySamples.IWcfService"bindingConfiguration="SafeServiceConf">

also modify your metadata exchange endpoint to use mexHttpsBinding

1 <endpoint address="mex" binding="mexHttpsBinding"contract="IMetadataExchange"/>

6. Modify your service behavior to look like this

01         <behavior name="WcfService.Service1Behavior">
02             <serviceMetadata httpGetEnabled="true"/>
03   <serviceDebug includeExceptionDetailInFaults="true" />
04   <serviceCredentials>
05     <userNameAuthentication
06          userNamePasswordValidationMode="Custom"
07          customUserNamePasswordValidatorType="MySamples.CustomValidator,WcfService"
08                                                                   />
10   </serviceCredentials>
11 </behavior>

It’s recommended that “Include exception in faults” should be disabled when moved to production.

7. Now you are almost ready to run the service however before you do this, make sure that you are running it in the IIS AND you have the SSL enabled on the server as specified in step 1 otherwise you’ll run into WCF error stating that there is no HTTPS endpoint available.

You should be able to run and see the service end point as follows.

8. Now that the service is done, let’s move towards building the client. Add the service reference to the service end point. You can do it either via entering the entire URL or using the discover feature.

9. Name your reference “Client” or modify your code appropriately. Following is the code for client implementation.

01 private static void Main(string[] args)
02  {
03     ServicePointManager.ServerCertificateValidationCallback = newRemoteCertificateValidationCallback(
04          delegate return true; });
06      var client = new WcfServiceClient();
07      GetCredentials();
08      client.ClientCredentials.UserName.UserName = username;
09      client.ClientCredentials.UserName.Password = password;
10      Console.Write(client.GetData(1));
11      client.Close();
12      Console.Read();
13  }

The RemoteCertificateValidationCallback part is used to programatically avoid the following warning which would popup due to self signed cert usage.

10. Now run the program.

You can see that for the right credentials, service will run just fine. Otherwise a security exception will be thrown.

Source code can be downloaded from here.WCFAuthSample

Feel free to drop me an email or comment here if you have any questions.

References and Further Readings:


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s