I have implemented Forms authentication in one project. In the forms authentication cookie I store the Login Id of the user. i.e.
FormsAuthentication.SetAuthCookie(LoginId, false);
I now need to read the cookie value on every request to get more information about the user and put this information in the HttpContext.Items property. The project is a MVC project that has both regular MVC Controllers as well as Web API controllers. Currently I have created two action filters - one for the MVC controllers and other for Web API Controllers where I read this value. So like
public class MyMvcFilter : AuthorizeAttribute
{
public override void OnAuthorization(AuthorizationContext filterContext)
{
var cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie != null)
{
var ticket = FormsAuthentication.Decrypt(cookie.Value);
filterContext.HttpContext.Items.Add("LoginId",ticket.Name);
}
base.OnAuthorization(filterContext);
}
}
and
public class MyFilter : ActionFilterAttribute
{
public override void OnActionExecuting(HttpActionContext actionContext)
{
base.OnActionExecuting(actionContext);
var cookie = HttpContext.Current.Request.Cookies[FormsAuthentication.FormsCookieName];
if (cookie == null)
{
return;
}
var ticket = FormsAuthentication.Decrypt(cookie.Value);
if (ticket == null)
{
return;
}
actionContext.Request.Properties.Add("LoginId", userId);
}
}
However the more I think of it, the more it looks like an ugly hack to me. What would be correct location where I can decrypt the authentication cookie and remains the same for MVC controller as well as Web API controller ?
I would:
Read the cookie on the
protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
}
In the above method....Convert the cookie to a ClaimsPrincipal. Like the below:
protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
IList<Claim> claimCollection = new List<Claim>
{
new Claim("http://www.mycompany.com/claims/LoginId, "123456" /* use info from cookie instead of 123456*/)
};
ClaimsIdentity claimsIdentity = new ClaimsIdentity(claimCollection, "My e-commerce website");
Console.WriteLine(claimsIdentity.IsAuthenticated);
ClaimsPrincipal customPrinc = new ClaimsPrincipal(claimsIdentity);
if (null != customPrinc)
{
Thread.CurrentPrincipal = customPrinc; /* Set here. But when you need to "get" it, use "System.Security.Claims.ClaimsPrincipal.Current" */
/* ASP.NET Authorization depends on value of HttpContext.Current.User.
* Consider putting ClaimsPrincipal into both HttpContext.Current.User and Thread.CurrentPrincipal */
HttpContext.Current.User = customPrinc;
/* Note the second setter is necessary so you don't lose it later on, learned the hard way by experience */
}
}
Retrieve the Claims Principal as needed..
/* MVC */
public override void OnAuthorization(System.Web.Mvc.AuthorizationContext filterContext)
{
/* the below should be what you set in the Application_PostAuthenticateRequest method */
IPrincipal currentClaimsPrinc = ClaimsPrincipal.Current;
}
/* WebAPI */
public override void OnAuthorization(HttpActionContext actionContext)
{
IPrincipal claimsPrincCurrent = ClaimsPrincipal.Current;
}
You could also do this:
adding claims to forms authentication in asp.net
or this:
or this: