Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

WCF Restful Service Form Authentication

0.00/5 (No votes)
6 Nov 2014 1  
WCF Restful Service Authentication without SSL Certificate

Introduction

WCF Restful Service methods can be accessed by URL only. I had to apply Authentication so that only Authentic users can access that method. I searched a lot to apply WCF Restful Service authentication using username password without SSL Certificate but could not find anything. Then I went for form Authentication.

Using the Code

First, we need to create one WCF service. I have created a service LoginSevice.svc for authenticating users. Also, I have created a user table and an edmx file importing that table.

 [AspNetCompatibilityRequirements(RequirementsMode = 
    AspNetCompatibilityRequirementsMode.Required)]
    [ServiceBehavior(InstanceContextMode = 
        InstanceContextMode.PerCall,IncludeExceptionDetailInFaults=true)]
    
    public class LoginService : ILoginService
    {

        TestEntities1 db = new TestEntities1();//Edmx entity Object
        public bool Login(string userName, string password)
        {
            bool returnValue = false;
            UserTable user;
            using (var ctx = new TestEntities())
            {
                user = ctx.UserTables.Where(one => one.UserName == userName).FirstOrDefault();
                if (user != null)
                {
                    returnValue = (user.Password == password);
                }
            }
            if (returnValue)
            {
                var loginTicket= new FormsAuthenticationTicket(
                        1,
                        userName,
                        DateTime.Now,
                        DateTime.Now.AddDays(1),
                        true,
                        user.Id.ToString()
                    );
                string encryptedTicket = FormsAuthentication.Encrypt(loginTicket);
                var cookie = new HttpCookie(FormsAuthentication.FormsCookieName, encryptedTicket);
                HttpContext.Current.Response.Cookies.Add(cookie);
            }
            return returnValue;
        }
    }

Now, we define OperationContract in ILoginService as shown below:

 [ServiceContract]
    public interface ILoginService
    {
        [OperationContract]
        bool Login(string userName, string password);
    }

Now, I added one more class for defining Restful Service Method named RestfullServiceMethod.

    [ServiceContract]
    [AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Required)]
    [ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall)]
    public class RestfullServiceMethod
    {
        [WebInvoke(UriTemplate = "/GetTest", 
        RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        public string GetTest()
        {
            return "test";
        }
    }   

Now in service web.config file, we need to change authentication mode to Form add apply Authorization like Allow user Deny User like below:

<configuration>
  <connectionStrings>
    <!-- For Edmx Connection String-->
    <add name="TestEntities" connectionString="
    metadata=res://*/WCFModel.csdl|res://*/WCFModel.ssdl|res://*/WCFModel.msl;
    provider=System.Data.SqlClient;provider connection string=&quot;
    Data Source=.;Initial Catalog=Test;User ID=sa;
    Password=sa;MultipleActiveResultSets=True&quot;" 
    providerName="System.Data.EntityClient" />
  </connectionStrings>

  <system.web>
    <compilation debug="true" targetFramework="4.0">
      <assemblies>
        <add assembly="System.Data.Entity, 
        Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />
      </assemblies>
    </compilation>
    <!--For apply authentication Mode form-->
    <authentication mode="Forms">
    </authentication>
    <!--For Access only Authorized user -->
    <authorization>
      <deny users="?" />
    </authorization>
  </system.web>
  
   <location path="LoginService.svc">
    <system.web>
      <authorization>
        <allow users="?" />
      </authorization>
    </system.web>
  </location>
 
   <system.webServer>
    <modules runAllManagedModulesForAllRequests="true">
      <add name="UrlRoutingModule" type="System.Web.Routing.UrlRoutingModule, 
      System.Web, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
    </modules>
  </system.webServer>
  
 <system.serviceModel>
    <behaviors>
      <serviceBehaviors>
        <behavior>
          <serviceMetadata httpGetEnabled="true" />
          <serviceDebug includeExceptionDetailInFaults="true" />
        </behavior>
      </serviceBehaviors>
    </behaviors>
    <serviceHostingEnvironment aspNetCompatibilityEnabled="true" 
    multipleSiteBindingsEnabled="true" />
    <standardEndpoints>
      <webHttpEndpoint>
        <standardEndpoint name="" helpEnabled="true" 
        automaticFormatSelectionEnabled="true" />
      </webHttpEndpoint>
    </standardEndpoints>
  </system.serviceModel>
</configuration>

Now, I need to consume that WCF Service normally Restful service method can call by URL using webRequest class but I need to apply authentication. That way, I validate the user first and pass that token in header request. For testing these, I have created one webapplication and that service Reference to that webapplication. Now, I am explaining the code of how to call that service in our webapplication after adding reference:

using System.ServiceModel;
using WebApplication1.LoginService;
using System.ServiceModel.Channels;
using System.Net;
using System.IO;
using System.Xml; 

namespace WebApplication1
{ 
  public partial class WebForm1 : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {  
            var sharedCookie = string.Empty;
            bool isValid;
            string data = string.Empty;
           var authClient = new LoginServiceClient();
          using (new OperationContextScope(authClient.InnerChannel))
            {  
              isValid = authClient.Login("test", "abc123");
              if (isValid)
               {
               var response = (HttpResponseMessageProperty)
               OperationContext.Current.IncomingMessageProperties[HttpResponseMessageProperty.Name];
               sharedCookie = response.Headers["Set-Cookie"];
               }
            }
          if (isValid)
            {               
                var request = 
                (HttpWebRequest)WebRequest.Create("http://localhost:9025/RestfullServiceMethod/GetTest");
                request.Timeout = 30000;
                request.Method = "POST";
                request.ContentType = "text/xml";
                request.Headers["Cookie"] = sharedCookie;
                
                HttpWebResponse res = null;
                res = (HttpWebResponse)request.GetResponse();
                Stream responseStream = res.GetResponseStream();
                var streamReader = new StreamReader(responseStream);
                string str = string.Empty;
                str = streamReader.ReadToEnd();
                lblResult.Text = str;
           }

We can also get user detail by that authentication token in RestfullService class:

[WebGet(UriTemplate = "/GetTest", 
RequestFormat = WebMessageFormat.Json, ResponseFormat = WebMessageFormat.Json)]
        public string GetTest()
        {
          string testcookie = HttpContext.Current.Request.Cookies
                [FormsAuthentication.FormsCookieName].Value;
          FormsAuthenticationTicket authTicket = FormsAuthentication.Decrypt(testcookie);
          string UserName=authTicket.Name;
          return "test";
        } 

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here