Click here to Skip to main content
15,893,594 members
Articles / Web Development / ASP.NET
Tip/Trick

WCF Restful Service Form Authentication

Rate me:
Please Sign up or sign in to vote.
4.57/5 (5 votes)
6 Nov 2014CPOL1 min read 32.5K   3   21   4
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.

C#
[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:

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

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

C#
[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:

C#
<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:

C#
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:

C#
[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, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
India India
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
QuestionPlease Upload SourceCode Pin
NF Khan15-Mar-17 22:11
NF Khan15-Mar-17 22:11 
Questionhave you consider to post this as a tip? Pin
Nelek8-Nov-14 12:54
protectorNelek8-Nov-14 12:54 
GeneralYou should submit to our IoT Tutorial Contest Pin
Kevin Priddle7-Nov-14 10:31
professionalKevin Priddle7-Nov-14 10:31 
QuestionRe: You should submit to our IoT Tutorial Contest Pin
Nelek8-Nov-14 12:52
protectorNelek8-Nov-14 12:52 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.