HttpContext.Current.User != HttpContext.User?

11,021

Your question tags say "aspnet-mvc (3 and 4)", so do you have the option of using the following to make your life easier? If you are using Simple Membership from the MVC 4 Internet Application template in VS2012 this will just work out of the box for you):

CreateUserAndAccount has the advantage that it's easy to set properties for the UserProfile as well, for example:

WebSecurity.CreateUserAndAccount(newUser.UserName, newUser.Password,
    new { FullName = newUser.FullName, Email = newUser.Email, Timezone = newUser.TZ });
Roles.AddUserToRoles(newUser.UserName, new[] {"admin", "user"});

Edit, I realise the above doesn't answer your original question about .User property equivalence.

HttpContext in a Controller is a property: Controller.HttpContext. HttpContext in global.asax.cs is the static class, so that's why you use HttpContext.Current. They refer to the same thing.

If you run the following code, you can see they are apparently the "same principal". So the question is what happened to the roles you assigned?

protected void Application_AuthenticateRequest(object sender, EventArgs e) {
    ...
    FormsIdentity identity = (FormsIdentity)HttpContext.Current.User.Identity;
    string[] roles = new string[] { "admin", "user" };
    identity.Label = "test label";
    System.Security.Principal.GenericPrincipal ppl = new System.Security.Principal.GenericPrincipal(identity, roles);            
    HttpContext.Current.User = ppl;
... }

public ActionResult Index() {
    bool isAdmin = HttpContext.User.IsInRole("admin");
    bool isAdmin2 = System.Web.HttpContext.Current.User.IsInRole("admin");
    System.Web.Security.FormsIdentity identity = (System.Web.Security.FormsIdentity)HttpContext.User.Identity;

    // The label is carried through from Application_AuthenticateRequest to Index.
    string label = identity.Label;
}

The problem is, you assigned a GenericPrincipal to .User. Depending on the RoleProvider, this can be overwritten (e.g. by the RoleManagerModule) during PostAuthenticateRequest and (for example) turned into a RolePrincipal. This can then defer back to the database (again depending on provider) to get the roles, so over-writing your roles. If you do the work in Application_OnPostAuthenticateRequest you might be ok.

Share:
11,021
Dr Blowhard
Author by

Dr Blowhard

Updated on June 04, 2022

Comments

  • Dr Blowhard
    Dr Blowhard almost 2 years

    Is HttpContext.Current.User in global asax not the same as HttpContext.User in an action method? I assigned the user some roles, but they seem to get lost.

    The code below shows what is happening. Both Asserts get hit when a user is logged on, first in global asax, then the action method. However they give different results.

    First this:

    protected void Application_AuthenticateRequest(object sender, EventArgs e)
    {
        // ... omitted some code to check user is authenticated
        FormsIdentity identity = (FormsIdentity)HttpContext.Current.User.Identity;
    
        string[] roles = new string[] { "admin", "user" };
    
        HttpContext.Current.User =
            new System.Security.Principal.GenericPrincipal(identity, roles);
    
        Assert(HttpContext.User.IsInRole("admin"));
    }
    

    Then this in my action method:

    public ActionResult Index()
    {
        bool isAdmin = HttpContext.User.IsInRole("admin");
    
        Assert(isAdmin); // this fails, isAdmin is false
    
        // ...
    }
    

    I used the following resources

    This SO answer

    http://csharpdotnetfreak.blogspot.com/2009/02/formsauthentication-ticket-roles-aspnet.html

  • Dr Blowhard
    Dr Blowhard almost 11 years
    beautiful thanks - changing to using PostAuthenticateRequest meant that I can see my roles in the controller. But also thanks for the heads up about SimpleMembershipProvider, I am using MVC4 so I might look at using it - either in this project or in the future
  • Andy Brown
    Andy Brown almost 11 years
    @SeanMill. Also see my answer here for more info about how SimpleMembership ties together.
  • jim tollan
    jim tollan over 10 years
    +1, ` protected void Application_OnPostAuthenticateRequest()` fixed and issue i had been having regarding roles being examined in Application_AuthenticateRequest. the simple change of event made a world of difference. thanks