views:

1657

answers:

3

I am using Forms authentication in my asp.net (3.5) application. I am also using roles to define what user can access which subdirectories of the app. Thus, the pertinent sections of my web.config file look like this:

<system.web>
  <authentication mode="Forms">
    <forms loginUrl="Default.aspx" path="/" protection="All" timeout="360" name="MyAppName" cookieless="UseCookies"  />      
  </authentication>
  <authorization >
    <allow users="*"/>
  </authorization>
</system.web>

<location path="Admin">
  <system.web>
    <authorization>
      <allow roles="Admin"/>
      <deny users="*"/>
    </authorization>
  </system.web>
</location>

Based on what I have read, this should ensure that the only users able to access the Admin directory will be users who have been Authenticated and assigned the Admin role.

User authentication, saving the authentication ticket, and other related issues all work fine. If I remove the tags from the web.config file, everything works fine. The problem comes when I try to enforce that only users with the Admin role should be able to access the Admin directory.

Based on this MS KB article along with other webpages giving the same information, I have added the following code to my Global.asax file:

protected void Application_AuthenticateRequest(Object sender, EventArgs e) {
    if (HttpContext.Current.User != null) {
        if (Request.IsAuthenticated == true) {    
            // Debug#1            
            FormsAuthenticationTicket ticket = FormsAuthentication.Decrypt(Context.Request.Cookies[FormsAuthentication.FormsCookieName].Value);
            // In this case, ticket.UserData = "Admin"                
            string[] roles = new string[1] { ticket.UserData }; 
            FormsIdentity id = new FormsIdentity(ticket);
            Context.User = new System.Security.Principal.GenericPrincipal(id, roles);
            // Debug#2
        }
    }
}

However, when I try to log in, I am unable to access the Admin folder (get redirected to login page).

Trying to debug the issue, if I step through a request, if I execute Context.User.IsInRole("Admin") at the line marked Debug#1 above, it returns a false. If I execute the same statement at line Debug#2, it equals true. So at least as far as Global.asax is concerned, the Role is being assigned properly.

After Global.asax, execution jumps right to the Login page (since the lack of role causes the page load in the admin folder to be rejected). However, when I execute the same statement on the first line of Page_Load of the login, it returns false. So somewhere after Application_AuthenticateRequest in Global.asax and the initial load of the WebForm in the restricted directory, the role information is being lost, causing authentication to fail (note: in Page_Load, the proper Authentication ticket is still assigned to Context.User.Id - only the role is being lost).

What am I doing wrong, and how can I get it to work properly? Thanks!


Update: I entered the solution below

A: 

Hi Yaakov, this is just a random shot, but are you getting blocked because of the order of authorization for Admin? Maybe you should try switching your deny all and your all Admin.

Just in case it's getting overwritten by the deny.

(I had code samples in here but they weren't showing up.

Jordan H.
A: 
Yaakov Ellis
+2  A: 

Here was the problem and solution:

Earlier in development I had gone to the Website menu and clicked on Asp.net configuration. This resulted in the following line being added to the web.config:

<system.web>
  <roleManager enabled="true" />
</system.web>

From that point on, the app was assuming that I was doing roles through the Asp.net site manager, and not through FormsAuthentication roles. Thus the repeated failures, despite the fact that the actual authentication and roles logic was set up correctly.

After this line was removed from web.config everything worked perfectly.

Yaakov Ellis