I have used a custom role-based security with forms authentication for my ASP.net web application. The roles, users are fetched from sql server. The framework is targeted for version 4.0.
I have used the code from https://msdn.microsoft.com/en-us/library/ff649337.aspx to create the FormsAuthenticationTicket upon login and then I have written the code to create a GenericPrincipal object in the Application_PreRequestHandlerExecute method.
string cookieName = FormsAuthentication.FormsCookieName;
HttpCookie authCookie = Context.Request.Cookies[cookieName];
if (authCookie == null) return;
FormsAuthenticationTicket authTicket;
try
{
authTicket = FormsAuthentication.Decrypt(authCookie.Value);
}
catch (Exception ex)
{
throw;
}
if (authTicket == null)
throw new Exception("");
FormsIdentity id = new FormsIdentity(authTicket);
if(HttpContext.Current.Session != null)
{
GenericPrincipal principal = new GenericPrincipal(id, new String[]{ "Manager"});
System.Threading.Thread.CurrentPrincipal = principal;
}
I have set a PrincipalPermission attribute to the page_load method of the redirect page as
[PrincipalPermissionAttribute(SecurityAction.Demand, Role="Manager")]
protected void Page_Load(object sender, EventArgs e)
{
}
I have added a button in this page, to simulate a postback. Upon first time load there is no security exception throw but if i click on the button there is a security exception thrown stating that "Request for principal permission denied.".
[SecurityException: Request for principal permission failed.]
System.Security.Permissions.PrincipalPermission.ThrowSecurityException() +3285333
System.Security.Permissions.PrincipalPermission.Demand() +419
System.Security.PermissionSet.DemandNonCAS() +117
RoleBasedSample.About.Page_Load(Object sender, EventArgs e)
However, this is not reproducible if i set the application pool to classic.
Is there is a reason why it fails only when application pool is set to Integrated mode?
GenericPrincipal principal = new GenericPrincipal(id, new String[]{ "Manager"});
HttpContext.Current.User = principal;
System.Threading.Thread.CurrentPrincipal = HttpContext.Current.User;
This solves the issue, not sure why this is necessary only when the pipeline is set to integrated and it works in classic without this code