Forms Authentication using Web API
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 ofDelegatingHandler
.
Hide Shrink Copy Code
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
Hide Copy Code
[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 webmethod's implementation.
Hide Copy Code
[HttpGet, Authorize(Roles = "admin"), Route("name")]
Calling from Client
The following jquery code shows how to make a Login call.
Hide Copy Code
$(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'sApplication_Start
method.
Hide Copy Code
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);
}
http://weblog.west-wind.com/posts/2013/Apr/18/A-WebAPI-Basic-Authentication-Authorization-Filter
No comments:
Post a Comment