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

Forms Authentication using Web API

0.00/5 (No votes)
16 Jun 2015 1  
If using Identity framework is not possible, one can add the old school forms authentication method.

Introduction

With the advent of OWIN middleware and Identity framework, traditional forms authentication is outdated since OWIN middleware and Identity framework takes care of everything in a better and organized manner. But sometimes, existing applications cannot be migrated to Identity framework due to one or the other reason, but Form Authentication user login is needed. For such situations, here is the workaround.

Background

There was an existing ASP.NET application using role based forms authentication, and was supposed to be migrated to ASP.NET MVC, but for some reason, the client wanted to stick to forms authentication.

Using the Code

To implement forms authentication, interception of both request and response is required which is done with the help of DelegatingHandler.

public class BasicAuthMessageHandler : DelegatingHandler
    {
        private const string BasicAuthResponseHeader = "WWW-Authenticate";
        private const string BasicAuthResponseHeaderValue = "Basic";

        public adminPrincipalProvider PrincipalProvider = new adminPrincipalProvider();

        protected override System.Threading.Tasks.Task<HttpResponseMessage> SendAsync(
            HttpRequestMessage request,
            CancellationToken cancellationToken)
        {
            AuthenticationHeaderValue authValue = request.Headers.Authorization;
            if (authValue != null && authValue.Parameter != "undefined" && 
				!String.IsNullOrWhiteSpace(authValue.Parameter))
            {
                string email = authValue.Parameter;
                if (HttpContext.Current.Session == null || 
		HttpContext.Current.Session["userToken"] == null || 
		string.IsNullOrEmpty(HttpContext.Current.Session["userToken"].ToString()))
                {
                    HttpContext.Current.Session["userToken"] = email;
                }
                else
                {
                    email = HttpContext.Current.Session["userToken"].ToString();
                }

                if (!string.IsNullOrEmpty(email))
                {
                    IPrincipal principalObj = PrincipalProvider.createPrincipal(email, "Admin");
                    Thread.CurrentPrincipal = principalObj;
                    HttpContext.Current.User = principalObj;
                }
            }
            return base.SendAsync(request, cancellationToken)
               .ContinueWith(task =>
               {
                   var response = task.Result;
                   if (response.StatusCode == HttpStatusCode.Unauthorized
                       && !response.Headers.Contains(BasicAuthResponseHeader))
                   {
                       response.Headers.Add(BasicAuthResponseHeader
                           , BasicAuthResponseHeaderValue);
                   }
                   return response;
               });
        }
    }

Principal object is used to assign role to a validated user, this principal object is added to HttpContext's user property.

Controller Login & Logout Web Method

       [HttpPost, AllowAnonymous, Route("login")]
        public async Task<HttpResponseMessage> Login([FromBody]LoginRequest request)
        {
            var loginService = new LoginService();
            LoginResponse response = await loginService.LoginAsync(request.username, request.password);
            if (response.Success)
            {
                FormsAuthentication.SetAuthCookie(response.Token, false);
            }
            return Request.CreateResponse(HttpStatusCode.OK, response);
        }

        [HttpPost, AllowAnonymous, Route("logout")]
        public void Signout()
        {
            FormsAuthentication.SignOut();

            if (HttpContext.Current.Session != null)
                HttpContext.Current.Session.Abandon();
        }

To setup role based authorization on webmethods, the following attributes are to be added on the top of web method's implementation.

[HttpGet, Authorize(Roles = "admin"), Route("name")]

Calling from Client

The following jquery code shows how to make a Login call.

$(document).ready(
    function () {
       $("#btnSubmit").click(function () {
          var usrname = $("#username").val();
          var pwd = $("#password").val();
          $.post("http://localhost:50750/api/loginctrl/login", 
		{ username: usrname, password: pwd }, function (result) {
                    alert(JSON.stringify(result));
                });
                       
          });
        });

Registering Delegating Handler

Before starting the execution of the project, custom Delegating Handler is to be registered with Application's Message Handlers. In this app, Delegating handler is registered inside Global.asax's Application_Start method.

 protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            GlobalConfiguration.Configure(WebApiConfig.Register);
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);

            var basicAuthMessageHandler = new WebAPI_FormsAuth.Helper.BasicAuthMessageHandler();
            basicAuthMessageHandler.PrincipalProvider = 
			new WebAPI_FormsAuth.Helper.adminPrincipalProvider();
            //start message handler
            GlobalConfiguration.Configuration.MessageHandlers.Add(basicAuthMessageHandler);
        }

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