19

I have just recently run into an issue running an asp.net web app under visual studio 2008. I get the error 'type is not resolved for member...customUserPrincipal'. Tracking down various discussion groups it seems that there is an issue with Visual Studio's web server when you assign a custom principal against the Thread.CurrentPrincipal.

In my code, I now use...

HttpContext.Current.User = myCustomPrincipal
//Thread.CurrentPrincipal = myCustomPrincipal

I'm glad that I got the error out of the way, but it begs the question "What is the difference between these two methods of setting a principal?". There are other stackoverflow questions related to the differences but they don't get into the details of the two approaches.

I did find one tantalizing post that had the following grandiose comment but no explanation to back up his assertions...

Use HttpConext.Current.User for all web (ASPX/ASMX) applications.

Use Thread.CurrentPrincipal for all other applications like winForms, console and windows service applications.

Can any of you security/dot.net gurus shed some light on this subject?

Community
  • 1
  • 1
yamspog
  • 17,114
  • 16
  • 59
  • 94

3 Answers3

25

The first thing that the HttpApplication object does when it acquires a thread is to set the thread's principal to the HttpContext's principal. This syncs up the principals.

If, however, you go and set the Thread's principal later on, the HttpApplication internally still has a different principal set for the user context. This is why you should always set it through the HttpContext.

(If you take a look in Reflector, you can see the complex code that runs when you do a "set" on HttpContext.User - it does a lot of internal stuff with IIS to properly set the principal.)

womp
  • 111,854
  • 24
  • 229
  • 262
  • 1
    Just a note for anyone reading this: even if you set HttpContext.User later, it does *not* seem to copy it to Thread.CurrentPrincipal. At least this was true for us in a message handler. We had to set both. – O'Rooney Jul 15 '15 at 23:49
6

Under a webforms application I believe Thread.CurrentPrincipal will be the principal for whomever is running the worker process (Thread).

HttpContext.Current.User will be the current logged in web-user.

In the case of a forms/wpf app it makes sense because the user you're running the application under is the one you're interested in.

Are you trying to masquerade the worker process or the logged in user?

Aren
  • 50,600
  • 8
  • 63
  • 100
  • 1
    Based on my local testing with IIS 7.5 .NET 4.5, this answer is wrong, and @womp's answer is correct. By default, Thread.CurrentPrincipal and HttpContext.Current.User both return the application/web user. System.Security.Principal.WindowsIdentity.GetCurrent() and Environment.UserDomainName + Environment.UserName both return the IIS Application Pool / worker process identity. – BateTech Feb 10 '15 at 20:16
  • 1
    I wonder if this changed since this answer was written 4.5 years ago, if so perhaps @yamspog can re-label the other answer as the accepted answer. – Aren Feb 18 '15 at 02:39
5

Does this article explain it?

http://www.hanselman.com/blog/CommentView.aspx?guid=22c42b73-4004-40ce-8af9-47f1b9b434ed

Here's an excerpt:

I have some code in an ASP.NET custom FormsAuthentication Login that looks something like this:

// This principal will flow throughout the request.
VoyagerPrincipal principal = new VoyagerPrincipal(yada, yada, yada);

// Attach the new principal object to the current HttpContext object
HttpContext.Current.User = principal;

It is called on the Global.asax's AuthenticateRequest so everything is all setup before the Page's events fire. It provides a custom IPrincipal that integrates our eFinance Server with ASP.NET. It's quite a lovely subsystem, IMHO.

Other operations count on being able to get this 'Call Context' IPrincipal from the current thread at any time. In another section of code someone was doing this in the MIDDLE of the HttpRequest (somewhere in the Page_Load) after having JUST called the routine above for the first time:

return Thread.CurrentPrincipal as VoyagerPrincipal;

In the instance where someone calls the first chunk of code then expects to be able to call the second chunk within the same HttpRequest, the Thread.CurrentPrincipal contains a GenericPrincipal populated much earlier by the HttpApplication. (Or a WindowsPrincipal, depending on your settings).

Entwickler
  • 255
  • 2
  • 12
Evan Nagle
  • 4,993
  • 1
  • 23
  • 23