Question

I'm trying to implement a custom principal and custom identity in a .NET MVC website. I've created a custom principal class which inherits from IPrincipal and a custom identity which inherits from IIdentity.

When a user logs in I set both Thread.CurrentPrincipal and HttpContext.Current.User to my custom principal. When I view either through the debugger the values are set with all the properties.

However once the request is complete and I try and request any other pages both Thread.CurrentPrincipal and HttpContext.Current.User are of type System.Security.Principal.GenericPrincipal and not my custom principal.

Do I need to do anything "extra" to get my custom principal out of the thread or HttpContext?

Thanks

Was it helpful?

Solution

The values in Thread.CurrentPrincipal and HttpContext.Current.User are not persisted between requests, they are rebuilt on each request. The best place for you to do this is probably in the Global.asax; write a function with the prototype:

void Application_PostAuthenticateRequest(object sender, EventArgs e)

That should get called after a user is authenticated on each request, which will allow you to set the principal how you would like.

OTHER TIPS

Overridding Principal in:

protected void Application_PostAuthenticateRequest(object sender, EventArgs e)

Instead of

protected void Application_AuthenticateRequest(object sender, EventArgs e)

In Global.asax.cs worked for me in an ASP web application

I would like to expand on the accepted answer slightly, hopefully I can save somebody a little bit of time.

In my case, the principal I used contained claims that were populated from the results of an external service, so I wanted to cache the results at login time.

I created a simple cache interface, IUserPrincipalCache, and registered it with the MVC DependencyResolver. At login, I build up the principal and add it to the cache. (Since your implementation may vary, I'll leave all that out.)

I then implemented this in Global.asax.cs:

protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
    if (User.Identity.IsAuthenticated)
    {
        var cache = DependencyResolver.Current.GetService<IUserPrincipalCache>();
        var claimsPrincipal = cache.FindUser(User.Identity.Name);
        if (claimsPrincipal != null)
        {
            Context.User = claimsPrincipal;
            Thread.CurrentPrincipal = claimsPrincipal;
        }
    }
}

I think it is important to point out the check for IsAuthenticated, since I could bypass the cache check in many cases. You also may not need to update Thread.CurrentPrincipal, I guess that depends on how you're using it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top