Custom IPrincipal not available in MVC5

I read a lot of questions and answers on this topic, but none of them helped me solve this problem.

The problem I am facing is that the HttpContext.Current.User property or just User is of type RolePrincipal instead of my user principal.

This is an MVC 5 web application using Windows authentication (intranet-only application). My custom principle is a subclass of WindowsPrincipal , and I used my own RoleProvider for use in Authorize attribute tags.

When I try to use a principal, casting it to my user principle from IPrincipal in the current HttpContext, I get an error message indicating that this is a type of RolePrincipal, which obviously cannot be attributed to my user principal. I set my custom principle in the Application_PostAuthenticationRequest event:

 protected void Application_PostAuthenticationRequest(object sender, EventArgs e) { if (User == null) return; using(EntityContext db = new EntityContext ()) { var user = db.Users.SingleOrDefault(u => u.ADName.Equals(User.Identity.Name)); HttpContext.Current.User = new PcsPrincipal((WindowsIdentity)User.Identity, user); } } 

When I put a breakpoint in this method, it seems to never be called, which may explain why it is not set in my user principle.

I reviewed the following QA, but they could not solve the problem:

What am I doing wrong to not have a Principal set? Let me know if more code should be posted.

EDIT: Setting HttpContext.Current.User to my account in the WindowsAuthentication.OnAuthenticate event will not solve this problem. Exactly the same behavior is manifested using this method.

+5
source share
2 answers

After constantly researching this problem, I finally found the answer with another SO question making my question look like a duplicate: MVC3 Windows Authentication overrides User.Identity

Below is the answer written by @Toby Jones (as editing his original question) that lead to a solution to my problem, but his answer is actually a combination of the two answers posted by @Erik Funkenbusch and @Darin Dimitrov. The answer is edited to correct some grammar and remove unnecessary information.

Option 1: override authorization request in Global.asax

The Application_AuthenticateRequest event should not be used because ( HttpContext.Current.User is null, even if Windows authentication is enabled), the user was not populated during Windows authentication, and therefore I can not use anything to get user information.

Application_AuthorizeRequest is the next in the chain and occurs after entering WindowsIdentity.

 protected void Application_AuthorizeRequest(object sender, EventArgs e) { if (User.Identity.IsAuthenticated && Roles.Enabled) { Context.User = new CustomPrincipal((WindowsIdentity)User.Identity); } } 

Option 2: Override the AuthorizeAttribute attribute

Here is the authorization attribute override

 public class CAuthorize : AuthorizeAttribute { protected override bool AuthorizeCore(HttpContextBase httpContext) { bool authorized = base.AuthorizeCore(httpContext); if (!authorized) return false; IIdentity user = httpContext.User.Identity; CPrincipal cPrincipal = new CPrincipal(user); httpContext.User = cPrincipal; return true; } } 

Then replace all AuthorizeAttributes with the custom version.

Option 1 handles everything around the world, and Option 2 handles everything on a more individual level using filters.

Personally, I decided to use the global.asax method, so I have user primary access available all over the world. Here is the actual code that resolved my issue:

 protected void Application_AuthorizeRequest(object source, EventArgs e) { if(User.Identity.IsAuthenticated && Roles.Enabled) { using (EntityContext db = new EntityContext ()) { var user = db.Users.Include("Roles").SingleOrDefault(u => u.ADName.Equals(User.Identity.Name)); if (user == null) return; PcsPrincipal principal = new PcsPrincipal((WindowsIdentity)User.Identity, user); Context.User = principal; } } } 
+1
source

You must set the user principle in the WindowsAuthentication_OnAuthenticate event, which occurs when the application authenticates the current request.

 protected void WindowsAuthentication_OnAuthenticate(object source, WindowsAuthenticationEventArgs e) { using(EntityContext db = new EntityContext ()) { var user = db.Users.SingleOrDefault(u => u.ADName.Equals(e.Identity.Name)); HttpContext.Current.User = new PcsPrincipal(e.Identity, user); } } 
+1
source

Source: https://habr.com/ru/post/1234046/


All Articles