Securing WCF REST Service using Windows Authentication

Posted by: Mahesh Sabnis , on 12/20/2009, in Category Windows Communication Foundation (WCF)
Views: 99599
Abstract: This article demonstrates that like normal WCF services, WCF REST base services can also be easily configured for security.
There are lots of articles and other resources available on WCF security. However recently one of my clients put across a requirement where WCF REST service was used in an application but before the data could be fetched from the REST URL, he wanted to pass the windows credentials and authenticate the user. The client was using a Windows application. I took this thought ahead and came up with a solution that I will be sharing through this article
The WCF service created with below interface and Web.Config:
Interface:
C#
[ServiceContract]
public interface IService1
{
    [OperationContract]
    [WebGet]
    string GetData(int value);
}
VB.NET
<ServiceContract> _
Public Interface IService1
      <OperationContract, WebGet> _
      Function GetData(ByVal value As Integer) As String
End Interface
Web.Config:
 <system.serviceModel>
    <services>
      <servicename="WCF_REST_UserNamePassword.Service1"
               behaviorConfiguration="WCF_REST_UserNamePassword.Service1Behavior">
        <endpointaddress=""binding="webHttpBinding"
                  contract="WCF_REST_UserNamePassword.IService1"
                    bindingConfiguration="wbBind">
        </endpoint>
      </service>
    </services>
    <behaviors>
      <serviceBehaviors>
        <behaviorname="WCF_REST_UserNamePassword.Service1Behavior">
          <serviceMetadatahttpGetEnabled="true"/>
          <serviceDebugincludeExceptionDetailInFaults="false"/>
          <serviceCredentials>
            <windowsAuthenticationallowAnonymousLogons="False"includeWindowsGroups="True"/>
          </serviceCredentials>
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <bindings>
      <webHttpBinding>
        <bindingname="wbBind">
          <securitymode="TransportCredentialOnly">
            <transportclientCredentialType="Windows"proxyCredentialType="Windows"/>
          </security>
        </binding>
      </webHttpBinding>
    </bindings>
 </system.serviceModel>
 
The ‘webHttpBinding’ uses security mode as ‘TransportWithCredential’ and uses ‘ClientCredentialType=Windows’. The Service behavior denies anonymous logon access.
To test this service, I have published it with IIS 7.0 and then tried to browse “Service.Svc”. It asks for the windows credential.
The console client application defined makes call to WCF REST service as shown below:
C#
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Xml;
using System.Net;
using System.Runtime.Serialization;
 
namespace Conole_REST_Client
{
    class Program
    {
        static void Main(string[] args)
        {
 
            var val = 100;
            Uri reqUri = new Uri("http://localhost/REST_Security/Service1.svc/GetData?value=" + val);
 
            Console.WriteLine("Enter USer Name");
            string userName = Console.ReadLine();
 
            Console.WriteLine("Entered Password");
            string password = Console.ReadLine();
 
            WebRequest req = WebRequest.Create(reqUri);
 
            req.PreAuthenticate = true;
 
            NetworkCredential credential = new NetworkCredential(userName, password);
 
            req.Credentials = credential;
 
            WebResponse resp = req.GetResponse();
 
 
            DataContractSerializer data = new DataContractSerializer(typeof(string));
            var res = data.ReadObject(resp.GetResponseStream());
 
            Console.WriteLine(res);
 
            Console.ReadLine();
        }
    }
}
 
VB.NET
Imports System
Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Xml
Imports System.Net
Imports System.Runtime.Serialization
 
Namespace Conole_REST_Client
      Friend Class Program
            Shared Sub Main(ByVal args() As String)
 
                  Dim val = 100
                  Dim reqUri As New Uri("http://localhost/REST_Security/Service1.svc/GetData?value=" & val)
 
                  Console.WriteLine("Enter USer Name")
                  Dim userName As String = Console.ReadLine()
 
                  Console.WriteLine("Entered Password")
                  Dim password As String = Console.ReadLine()
 
                  Dim req As WebRequest = WebRequest.Create(reqUri)
 
                  req.PreAuthenticate = True
 
                  Dim credential As New NetworkCredential(userName, password)
 
                  req.Credentials = credential
 
                  Dim resp As WebResponse = req.GetResponse()
 
 
                  Dim data As New DataContractSerializer(GetType(String))
                  Dim res = data.ReadObject(resp.GetResponseStream())
 
                  Console.WriteLine(res)
 
                  Console.ReadLine()
            End Sub
      End Class
End Namespace
 
The NetworkCredential class is used to define client credentials and the important point here is that the ‘PreAuthenticate’ property of the WebRequest class is set to ‘true’. This indicates that credential information will be sent when the client makes a request to the service. The NetworkCredential object is passed to the ‘Credential’ property of the ‘WebRequestClass’.
After running the application the output will be displayed as below:
Output

Conclusion: As like normal WCF services, WCF REST base services can also be easily configured for security.

This article has been editorially reviewed by Suprotim Agarwal.

Absolutely Awesome Book on C# and .NET

C# and .NET have been around for a very long time, but their constant growth means there’s always more to learn.

We at DotNetCurry are very excited to announce The Absolutely Awesome Book on C# and .NET. This is a 500 pages concise technical eBook available in PDF, ePub (iPad), and Mobi (Kindle).

Organized around concepts, this Book aims to provide a concise, yet solid foundation in C# and .NET, covering C# 6.0, C# 7.0 and .NET Core, with chapters on the latest .NET Core 3.0, .NET Standard and C# 8.0 (final release) too. Use these concepts to deepen your existing knowledge of C# and .NET, to have a solid grasp of the latest in C# and .NET OR to crack your next .NET Interview.

Click here to Explore the Table of Contents or Download Sample Chapters!

What Others Are Reading!
Was this article worth reading? Share it with fellow developers too. Thanks!
Share on LinkedIn
Share on Google+

Author
Mahesh Sabnis is a DotNetCurry author and a Microsoft MVP having over two decades of experience in IT education and development. He is a Microsoft Certified Trainer (MCT) since 2005 and has conducted various Corporate Training programs for .NET Technologies (all versions), and Front-end technologies like Angular and React. Follow him on twitter @maheshdotnet or connect with him on LinkedIn


Page copy protected against web site content infringement 	by Copyscape




Feedback - Leave us some adulation, criticism and everything in between!
Comment posted by Piyush on Monday, December 21, 2009 1:48 AM
Very useful info
Comment posted by Ravi Ramchandani on Tuesday, August 31, 2010 4:36 AM
Thanks for this helpful article.

Basically I want to ask if this is applicable to WCF REST 4.0 in II 7.0 since their is no .svc file in .NET 4.0 REST.
Your inputs would be greatly appreciated
Thank you

Regards,
Ravi
Comment posted by Naftali on Thursday, January 23, 2014 6:48 AM
Hi,
thanks for the clear article.
still I have some issue with it.
I have an exception while I'm trying it.
Cannot add the 'serviceCredentials' behavior extension to 'REST' endpoint behavior because the underlying behavior type does not implement the IEndpointBehavior interface

what can solve it?
I can't see the C# code for behavior class. it's there or I can do it without it?
Comment posted by Mohit on Thursday, September 18, 2014 12:33 PM
how can i call this using jquery ajax call?
Comment posted by prabhu on Wednesday, March 18, 2015 12:31 PM
Security settings for this service require Windows Authentication but it is not enabled for the IIS application that hosts this service.

I am encountering this issue.  Can you please help on this how to resolve.
<?xml version="1.0"?>
<configuration>

  
  <!-- Connection String Start-->
  <connectionStrings>
  </connectionStrings>
  <!--Connection String End-->
  
  
  <!-- ServiceModel Start-->
  <system.serviceModel>

       <serviceHostingEnvironment aspNetCompatibilityEnabled="true"/>
    
       <!--Services Start-->
       <services>
         <service name="MobileAppWCFRestService.MobileAppService" behaviorConfiguration="mexBehavior">

           <endpoint address=""
           binding="webHttpBinding"
                          contract="MobileAppWCFRestService.IMobileAppService"
                          behaviorConfiguration="mexBehavior"
                          bindingConfiguration="StreamedBinding"
                          bindingName="StreamedBinding">

                  <identity>
         <dns value="localhost"/>
             </identity>

                </endpoint>

           <endpoint contract="IMetadataExchange" binding="webHttpBinding" address="mex" bindingConfiguration="StreamedBinding"/>        



         </service>
       </services>
       <!--Services End-->
    

    <!--Behaviors Start-->
    <behaviors>
      <serviceBehaviors>
        <behavior name="mexBehavior">

          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="false"/>

  
   

        </behavior>
      </serviceBehaviors>

      <endpointBehaviors>
        <behavior name="mexBehavior">
          <webHttp/>
        </behavior>
      </endpointBehaviors>

    </behaviors>
    <!-- Behaviors End-->


    <bindings>
      <webHttpBinding>
        <!-- buffer: 64KB; max size: 64MB -->
        <binding name="StreamedBinding" maxReceivedMessageSize="67108864">

      
  
    <security mode="TransportCredentialOnly">
            <transport clientCredentialType="Windows" />
          </security>

        </binding>
      </webHttpBinding>
    </bindings>

  </system.serviceModel>
  <!-- ServiceModel End-->
  
  
  <!-- WebServer Start-->
  <system.webServer>
    <modules runAllManagedModulesForAllRequests="true"/>
    <httpProtocol>
      <customHeaders>
        <add name="Access-Control-Allow-Origin" value="*"/>
        <add name="Access-Control-Allow-Headers" value="Content-Type, Accept"/>
        <add name="Access-Control-Allow-Methods" value="POST,GET,OPTIONS"/>
        <add name="Access-Control-Max-Age" value="1728000"/>
      </customHeaders>
    </httpProtocol>
    <directoryBrowse enabled="true"/>
  </system.webServer>
  <!-- WebServer End-->

  <!--System.Web Start-->
  <system.web>

   <customErrors mode="Off"/>
   <authentication mode="Windows" />

     <compilation debug="true">
      <assemblies>
        <add assembly="System.Configuration, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B03F5F7F11D50A3A"/>
      </assemblies>
    </compilation>

  </system.web>

  <!-- System.web.End-->

  
</configuration>