Windows Authentication on REST Enabled WCF Service

Enabling Windows Authentication on a REST enabled service is a relatively easier task than it appears to be. To test that Windows Authentication is enabled successfully or not use another browser than Internet Explorer because IE will automatically do an NTLM negotiation with domain credentials. So when the REST service is running in IE, it is not prompting for user credentials. 

Service 

I am going to use a very simple contract as REST service. 

Contract 

namespace RestserviceWindows
{
   [ServiceContract]
    public interface IService1
    {
        [OperationContract]
        [WebGet()]
        string GetData();
     }
}

Service implementation 

namespace RestserviceWindows
{
public class Service1 : IService1
    {
        public string GetData()
        {
            return "Testing Windows Authentication with REST service";
        }
      }
}

Configuring the Service

Method #1: Using Factory class 
  1. Create a simple REST service. To create a REST service navigate to "File" -> "New" -> "Project..." -> "Web" and select the "WCF Service Application" project template. 
  2. WCF will create default endpoints inside System.ServiceModel. Delete both the default endpoints.  Delete the following end points:

    <
    endpoint address="" binding="wsHttpBinding" contract="RestserviceWindows.IService1">         
             <identity>
                <dns value="localhost"/>
              </identity>
           </endpoint>      
    <endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange"/>

  3. Right-click on the .SVC file. If your service name is Service1 then right-click on Service1.svc.  After right-clicking select View Markup. Add the Factory here:

    <%@ ServiceHost Language="C#" Debug="true" Service="RestserviceWindows.Service1" CodeBehind="Service1.svc.cs" Factory="System.ServiceModel.Activation.WebServiceHostFactory" %>

  4. Host the service in IIS. To host it, right-click on the service and "Publish in IIS". 
  5. Configure IIS for Windows Authentication. 
The preceding 5 steps are required to host a REST service in IIS with Windows Authentication. 

Method #2: Configuring End Point without Meta Data
  1. Create a simple REST service. To create a REST service navigate to "File" -> "New" -> "Project..." -> "Web" and select the "WCF Service Application" project template. 
  2. Delete the endpoint address for MEX  and binding mexHttpBinding 
  3. Configure EndPoint to enable REST service. 
  4. Configure EndPoint to enable Windows Authentication on the service. 
  5. Configure End Point behavior. 
  6. Ensure that there is no factory class provided for the service in the markup of the .svc

    <%@ ServiceHost Language="C#" Debug="true" Service="RestserviceWindows.Service1" CodeBehind="Service1.svc.cs" %>
  7. Host the service in IIS. To host it, right-click on the service and "Publish in IIS". 
  8. Configure IIS for Windows Authentication. 

    <
    system.serviceModel>
    <services>
    <service name="RestserviceWindows.Service1" behaviorConfiguration="RestserviceWindows.Service1Behavior">                            
    <endpoint address="" binding="webHttpBinding" contract="RestserviceWindows.IService1" bindingConfiguration ="RESTBINDING" behaviorConfiguration ="REST">         
    <identity>
    <dns value="localhost"/>
    </identity>
    </endpoint>      
    </service>
    </services>
    <behaviors>
    <serviceBehaviors>
    <behavior name="RestserviceWindows.Service1Behavior">                                            
    <serviceMetadata httpGetEnabled="true"/>                                              
    <serviceDebug includeExceptionDetailInFaults="false"/>
    </behavior>
    </serviceBehaviors>
         <endpointBehaviors>
            <behavior name ="REST">
              <webHttp/>
            </behavior>
          </endpointBehaviors>
    </behaviors>
        <bindings>
          <webHttpBinding>
            <binding name ="RESTBINDING">
              <security mode ="TransportCredentialOnly">
                <transport clientCredentialType ="Windows"/>
              </security>
            </binding>
          </webHttpBinding>
        </bindings>
    </system.serviceModel>
Method #3: Configuring End Point with Meta Data

So far in the above two methods, Meta Data is not being exposed, because mexHttpBinding only supports anonymous binding.  So to enable Windows Authentication on mexHttpBinding , we need to configure IMetaDataContract with some other binding like basicHttpBinding or webHttpBinding.
  1. Create a simple REST service. To create a REST service navigates to "File" -> "New" -> "Project..." -> "Web" and select the "WCF Service Application" project template. 
  2. Configure EndPoint to enable REST service. 
  3. Configure EndPoint to enable Windows Authentication on the service. 
  4. Configure End Point behavior for both End Points. 
  5. Ensure that there is no factory class provided for the service in the markup of the .svc

    <%@ ServiceHost Language="C#" Debug="true" Service="RestserviceWindows.Service1" CodeBehind="Service1.svc.cs" %>
  6. Host the service in IIS. To host it right-click on service and Publish in IIS. 
  7. Configure IIS for Windows Authentication. 

    <
    system.serviceModel>
        <services>                      
          
    <
    service name="RestserviceWindows.Service1" behaviorConfiguration="RestserviceWindows.Service1Behavior">                                     
           <endpoint address="" binding="webHttpBinding" contract="RestserviceWindows.IService1" bindingConfiguration ="RESTBINDING" behaviorConfiguration ="REST">         
              <identity>
                <dns value="localhost"/>
              </identity>
            </endpoint>      
           <endpoint address="mex" binding="webHttpBinding" contract="IMetadataExchange" bindingConfiguration ="RESTBINDING"/>
           </service>
        </services>
        <behaviors>
           <serviceBehaviors>
               <behavior name="RestserviceWindows.Service1Behavior">                                            
                  <serviceMetadata httpGetEnabled="true"/>                                               
                  <serviceDebug includeExceptionDetailInFaults="false"/>
               </behavior>
           </serviceBehaviors>
          <endpointBehaviors>
            <behavior name ="REST">
              <webHttp/>
            </behavior>
          </endpointBehaviors>
       </behaviors>
        <bindings>
          <webHttpBinding>
            <binding name ="RESTBINDING">
              <security mode ="TransportCredentialOnly">
                <transport clientCredentialType ="Windows"/>
              </security>
            </binding>
          </webHttpBinding>     
        </bindings>
    </system.serviceModel>

Note:  The binding for the IMetaDataExchange contract is webHttpBinding. 

Consuming the Service 

To enable a client to consume a Windows Authenticated WCF service, the client needs to pass domain credentials. If a HttpClient is used by the client to consume the service then the client must set the credentials like:

clt.TransportSettings.Credentials=System.Net.CredentialCache.DefaultCredentials;

where clt is an instance of a HttpClient.
  1. Add  Microsoft.Http and System.RunTime.Serlization assembly at reference
  2. Add namespace of Microsoft.Http and System.Runtime.Serlization
  3. Create an instance of HttpClient 
  4. Set the default credential from the cache. 
  5. Perfrom HTTP operation. 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Http;
using System.Runtime.Serialization;
using System.Net;
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string url = "http://localhost/RESTTESTING/Service1.svc/GetData";
            HttpClient clt = new HttpClient();           
            clt.TransportSettings.Credentials = System.Net.CredentialCache.DefaultCredentials;
            HttpResponseMessage msg = clt.Get(url);
            string str = msg.Content.ReadAsDataContract<string>();
            Console.WriteLine(str);
            Console.Read();
        }
    }
}

Up Next
    Ebook Download
    View all
    Learn
    View all