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
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.