Basic Authentication On WCF Rest

Posted by on January 27, 2012 in Software Development | 0 comments

Basic Authentication On WCF Rest

This article explains a method to secure a REST based service using basic authentication. The service itself is implemented using Microsoft Windows Communication Foundation. The authentication of the credentials should be possible against any type of back-end.

For example authenticate against active directory, custom file or a database. Default, Basic Authentication is possible in combination with WCF and IIS, authentication is only possible then against active directory. This article and provided source code can be used in two ways. First just download the code, go down to the use the code part and implement your WCF service using Basic authentication. Second you can use the article to learn about what exactly is Basic Authentication and how can WCF be extended in a simple way.

Basic Authentication

Basic authentication is a standard protocol defined within Http 1.0 that defines an authentication scheme. In this scheme the client must authenticate itself with a user-id and password. Basic authentication is described in RFC 2617. When a client requests a resource from a site that is protected using Basic Authentication the server returns a 401 “Not authorized” response. Inside this response the server has added an sign that the site is protected using Basic Authentication. The server adds WWW-Authenticate: Basic realm=”site” to the header of the response, Basic indicates that the authentication scheme is Basic Authentication. Realm is an string that indicates which part of the site is protected. It has no further usage in the actual authentication mechanism itself.

An internet browser generates a dialog based on this response message, this dialog shows the realm and allows a user to enter a user name and password.

Request Response Flow Basic Authentication

When a user enters the user name and password, the client resents the request but adds “Authorization: Basic SGVsbG8gQmFzZTY0″ to the header of the request. The strange characters after Basic are the user name and password separated by a single colon “:” in a base64 encoded string. The server decodes the string, extracts the credentials and validates them against the back-end. When the credentials are correctly validated the server returns the requested content to the client.

Request Response Flow Basic Authentication

Extending WCF Rest

WCF REST is part of the WCF Rest starter kit. Unlike standard WCF, the WCF starter kit provides a simple way to apply behaviour to all server operations. Adding this behavior to normal WCF can get fairly complex. WCF Rest uses Request Interceptors. Request interceptors shield you from the more complex extensibility points. Request Interceptors are executed at the WCF channel level and enable you to interpret the incoming request and generate an appropriate response.

public class MyRequestInterceptor : RequestInterceptor
{
  public override void ProcessRequest
        (ref RequestContext requestContext)
  {
    //Access request with requextContext.RequestMessage
  }
}

By deriving a new class from the RequestInterceptor base class you create a custom request interceptor. The method ProcessRequest is executed for every request that arrives at the service. Inside this method we read the header of the request and decode the base64 encoded string if it is present. If it is not present we generate a response that includes WWW-Authenticate: Basic realm=”site” in the header.

Linking the custom RequestInterceptor to the service

The RequestInterceptor can be linked to the service by creating a custom ServiceHostFactory. The ServiceHostFactory is responsible for provides instances of ServiceHost in managed hosting environments. By Managed hosting environments Microsoft means IIS hosted services. The CreateServiceHost method of the ServiceHostFactory creates a new WebServiceHost and adds the new RequestInceptor to the Interceptors collection.

public class BasicAuthenticationHostFactory :
   ServiceHostFactory
{
  protected override ServiceHost CreateServiceHost
         (Type serviceType, Uri[] baseAddresses)
  {
    var serviceHost = new WebServiceHost2(serviceType,
        true, baseAddresses);
    serviceHost.Interceptors.Add(
        requestInterceptorFactory.Create("DataWebService",
            new CustomMembershipProvider()));
    return serviceHost;
  }
}

This new ServiceHostFactory is linked to the service through the markup file (.svc) of the service. Inside the markup, you override the host factory of the service.

ServiceHost Language="C#" Debug="true"
   Service="WCFServer.Service"
   Factory="WCFServer.BasicAuthenticationHostFactory"

Custom MembershipProvider

The provided source code uses a MembershipProvider to actually authenticate the credentials of the client. You can write your own MembershipProvider by deriving from MembershipProvider. The only method that needs to be implemented is the ValidateUser method. This is the method the code uses to validate the user. This customer MembershipProvider is linked to the RequestInterceptor in the CreateServiceHost method of the ServiceHostFactory.

public class CustomMembershipProvider : MembershipProvider
{
  public override bool ValidateUser(string username,
        string password)
  {
    //perform validation return false;
  }
  ...

Security context

After we have authenticated the incoming request, we have to create and set the security context. This enables the usage of the client credentials inside a service method. WCF uses the thread local ServiceSecurityContext for this. After the request has been authenticated, a new ServiceSecurityContext is created and added to the incoming request. This enables retrieving the user name inside the service method with ServiceSecurityContext.Current.PrimaryIdentity.Name

Using the code

If you want to secure your own WCF REST service with Basic Authentication, you need to execute the following steps:

  • Add a reference to the BasicAuthenticationUsingWCF assembly
  • Create a new membership provider derived from MembershipProvider
  • Implement the ValidateUser method against your back-end security storage
  • Create a custom BasicAuthenticationHostFactory
  • Add the new BasicAuthenticationHostFactory to the markup of the .svc file

Points of Interest

Although Basic Authentication is a method to secure a web site or service, the authentication mechanism itself is not secure. The user name and password are send base64 encoded over the internet. To make this more secure, the server should offer the service using https. Https secures the channel so that the base64 encoded user name and password cannot be decrypted.

This article and source code are based on the example of Pablo M. Cibraro who deserves the credit for the solution. The provided sourcecode is developed using TDD and uses the NUnit framework for creating and executing tests. Rhino mocks is used as a mocking framework inside the unit tests.

Source Code

The source can be found at CodeProject