Distributed architectures quite often require that the user credentials need to be delegated from one layer to another - often crossing system boundaries. Kerberos delegation is the technology most often used to implement this authentication scenario. Unfortunately Kerberos is often perceived as complex and hard to configure. That is the reason why many architects tend to use workarounds to avoid Kerberos. However, these workarounds cannot provide the same benefit and flexibility. This article is supposed to help you dealing with the challenges of building a solution based on Kerberos. I will walk you through the steps required for connecting a client application to SharePoint via a WCF Web Service and delegating the client’s credentials to the back-end service. After reading this article you will be able to delegate user credentials in your WCF solution which will provide you more flexibility and new options in your designs.

Architecture

My demo simulates a distributed application where a client application invokes a WCF Web Service which implements the business logic plus the access layer for connecting to a back-end service. In my design the web service will upload a document (C:\Temp\Test.txt) to a back-end SharePoint. The web service will use the SharePoint Client Object Model for the back-end communication.

Note:
The back-end doesn’t need to be SharePoint. This demo also applies (with minor changes) to any back-end service with Kerberos support.

Architecture

The objective of this demo is to upload a file from the web service to SharePoint with the credentials of the user running the client application. This scenario, called a “Double Hop”, can only be implemented using Kerberos.

Infrastructure

I will use 3 machines in this demo. GREEN is my Domain Controller and I will also run the client application on this machine. RED hosts the WCF Web Service on Internet Information Services (IIS). WHITE is a single server installation of SharePoint Server.

Infrastructure

All machines are joined to colors.selfhost.corp.microsoft.com and all services run under designated service accounts.

Basic IIS Configurations

  1. Create a new service user on the domain controller for the AppPool that will host the WCF Web Service (e.g. COLORS\IIS_SERVICE_RED).
  2. Create a new Application Pool in the Internet Information Services (IIS) Manager (e.g. WebServices) on the server you want to deploy the web service to.
    1
  3. Change the AppPool service user to the new service user by clicking Advanced Settings in the Actions Pane and changing the Identity property.
    2
  4. Make sure that you have HTTP Activation in “Add Roles and Features” installed. 
    3

Web Service: KRBServer

My web service in this demo is quite basic. It only has one operation called UploadFile which accepts only one parameter – the path of the file which is stored locally on the server and will be uploaded to SharePoint.

IKrbService1

using System.ServiceModel;

namespace KRBServer
{
[ServiceContract]
public interface IKrbService1
{
[OperationContract]
bool UploadFile(string localPath);
}
}

KrbService

using System.ServiceModel;
using Microsoft.SharePoint.Client;

namespace KRBServer
{
public class KrbService1 : IKrbService1
{
[OperationBehavior(Impersonation = ImpersonationOption.Required)]
public bool UploadFile(string localPath)
{
var fileCreationInformation = new FileCreationInformation
{
Content = System.IO.File.ReadAllBytes(localPath),
Url = "http://white.colors.selfhost.corp.microsoft.com/Shared%20Documents/Test.txt",
Overwrite = true,
};

var context = new ClientContext("http://white.colors.selfhost.corp.microsoft.com");
var web = context.Web;

var documents = web.Lists.GetByTitle("Documents");

var uploadFile = documents.RootFolder.Files.Add(fileCreationInformation);

context.Load(uploadFile);
context.ExecuteQuery();

return true;
}
}
}

In the service implementation I use the SharePoint Client Object Model to connect to SharePoint and upload a local file to the Documents library.

Note:
Make sure the implementation of your operation is decorated with [OperationBehavior(Impersonation = ImpersonationOption.Required)] which will be important when it comes to delegation in Part 2 of this blog post.

Client Application: KRBClient

The client application is even simpler than the service: It’s a console application which has a service reference to the web service and initiates the upload process by invoking the UploadFile operation.

Note:
In this demo I use IncludeExceptionDetailInFaults (see
Fault Contract) for handling errors. This is very convenient for debugging purposes - it should not be used in production, though.

Program.cs

using System;
using System.ServiceModel;

namespace KRBClient
{
class Program
{
static void Main(string[] args)
{
var client = new KrbSvc.KrbService1Client();

try
{
client.UploadFile(@"C:\Temp\Test.txt");
Console.Out.WriteLine("SUCCESS: Uploading File.");
}
catch (FaultException faultEx)
{
Console.WriteLine("ERROR: Uploading File. \n" + faultEx.Message + faultEx.StackTrace);
}
Console.In.ReadLine();
}
}
}

Configuring SharePoint to allow Kerberos Authentication

  1. Open “Active Directory Users and Computers” on your domain controller.
  2. Enable Advance Features (View –> Advanced Features).
  3. Open Properties of your SharePoint service user.
  4. Switch to the Attribute Editor tab and select servicePrincipalName.
    6
  5. Add the following SPN values (change hostname as required for your configuration).
    7
  6. Note:
    After creating the SPN values verify that there aren’t any duplicate SPNs by running the following command from the Command Prompt: setspn –x
  7. Open SharePoint Central Administration and go to Manage web applications.
  8. Select your web application and choose Authentication Providers.
    4
  9. Select your Zone (Default) and change the value for Integrated Windows authentication to Negotiate (Kerberos).
    2
  10. Verify that your clients can connect to SharePoint using Kerberos by opening the document library from your web browser.
  11. Open Event Viewer on your SharePoint server and check for events with Event ID 4624. Verify that the Logon Process of this Audit Success Event is Kerberos.
    8

In Part 2 of my WCF and Kerberos delegation post I will show you how to configure the web service and the client to use Kerberos authentication. I will also demonstrate how to set up constrained delegation to solve the double-hop issue.