Thread.CurrentPrincipal not authenticated when creating from delegate

Sep 23, 2014 at 8:48 AM
More details here: http://stackoverflow.com/questions/15964244/using-asp-net-web-api-my-executioncontext-isnt-flowing-in-async-actions

But basically the problem is doing something like this:
container.RegisterPerWebRequest<IPrincipal>(() => Thread.CurrentPrincipal);
Doesn't appear to resolve to the principal that contains the claims for the client authenticated using a bearer token.

I'm not 100% clear on the lifecycle of the current principal and at what point it gets set, it appears in this instance not to be set before authorization and constructor of an ApiController.

Could anyone suggest an alternative to injecting this into a Class which is injected into an ApiController?

Cheers
Coordinator
Sep 23, 2014 at 8:52 AM
Edited Sep 23, 2014 at 8:52 AM
Try this:
container.RegisterPerWebRequest<IPrincipal>(
    () => HttpContext.Current != null ? HttpContext.Current.User : Thread.CurrentPrincipal);
Sep 23, 2014 at 9:15 AM
Hi there cheers for the response, unfortunately that doesn't appear to work either.

I have tried accessing the HttpContext.Current property directly by debugging and it contains the same values. Unfortunately I couldn't just swap out as the thing I am injecting the value directly into (in container has multiple constructors (I also use it for passing data back to a web api client using a remote service call), to clarify this is my actual call:
container.Register<ICurrentClaims>(() => new CurrentClaims(Thread.CurrentPrincipal), scopedLifestyle);
So swapping for this still doesn't work:
container.Register<ICurrentClaims>(() => new CurrentClaims(HttpContext.Current.User), scopedLifestyle);
Which is a helper method I use to extract the claims from the principal and provide a typed model to access them.
Sep 23, 2014 at 11:47 AM
Hi in case it helps I have created a very contrived and bare bones solution that demonstrates the problem I face at the moment, which can be found here:

http://www.filedropper.com/principalinjector

Its a Visual Studio 2013 solution, with 2 projects: API and Test client (which should both start at the same time).

The key part of interest is the DefaultController which has a constructor with IPrincipal injected into it and a Get methods to return a list of roles to the client.

The code shows that the IPrincipal that is injected is not Authenticated and instead it will return the roles from the ApiController.User instead.

Anyway guidance much appreciated...

Cheers
Coordinator
Sep 23, 2014 at 12:05 PM
I don't see any configuration in your web.config that defines Windows Authentication. I would say that not configuring this will cause the principal to be anonymous. You should configure IIS and your web application correctly to allow the user information to be passed into the application.
Sep 23, 2014 at 1:01 PM
Hi Steven, for this app I am not actually using Windows authentication, the claims are being set Bearer Authentication handler which unfortunately I cannot get into to see how.

I'm not actually clear at what point in the pipeline The current principal is actually set, but the fact that the ApiController can can access it via its User property shows that t?hey are being set, just not when injecting into the Controller constructor.
/
I had a look at the ApiController source code and it exposes the RequestContext.Principal:
        /// <summary>Gets or sets the current principal associated with this request.</summary>
        /// <remarks>The setter is intended for unit testing purposes only.</remarks>
        public IPrincipal User
        {
            get { return RequestContext.Principal; }
            set { RequestContext.Principal = value; }
        }
which I assume I don't have access to from the injector?
Coordinator
Sep 23, 2014 at 1:32 PM
I believe the RequestContext.Principal is set by a handler in the pipeline after the controller is created, but I'm not sure. You'll have to dig deeper. Your scenario is definately not a default one, since injecting HttpContext.Current.User or Thread.CurrentPrincipal has always worked for me.
Sep 23, 2014 at 2:02 PM
Hi Steven, thanks for taking the time to look into it, I was just hoping I had done something incredibly dumb and obvious (which might still be the case).

It looks like I will have to dive deeper and it appears that the context may be set as part of the HttpRequestMessage request so I will start looking that route, otherwise I will fall back to using a property setter (which obviously creates some temporal coupling but will do for now).

Anyway thanks again. I will post here if I find a solution.
Sep 23, 2014 at 3:11 PM
Ok update on this post, I followed this documentation to get the HttpRequestMessage, and that does indeed hold the claims!
(((Microsoft.Owin.OwinContext)(message.CurrentMessage.Properties["MS_OwinContext"])).Authentication).User
So I'm going to speculate that the HttpRequestMessage is actually used to set the RequestContext.Principal on the ApiController (in fact the AuthorizeAttribute also gets it as well).

Also on a whim I decided to see if I could access the Thread.CurrentPrincipal by deferring access until it is actually need and I found that I could using Lazy loading, so after reading the documentation here and changing the RegisterWebApiRequest line to:
container.RegisterWebApiRequest<Lazy<IPrincipal>>(() => new Lazy<IPrincipal>(() => Thread.CurrentPrincipal));
This does indeed work!
So now I'm torn between writing a wrapper 'ClaimsProvider' to extract the claims from the HttpRequestMessage and inject that (which is what I actually care about), or just stick to lazy loading the principal after injection. I'm not sure what the pros and cons of each are at this stage but leaning toward a ClaimsProvider... but at least I have a workable solution :-D

Anyway cheers for providing such excellent documentation, I found what I needed in the end.
Marked as answer by dot_NET_Junkie on 9/28/2014 at 4:01 AM