-
Notifications
You must be signed in to change notification settings - Fork 598
ClaimsPrincipal.Current does not return the ClaimsPrincipal of the caller. #322
Comments
/cc @davidfowl, as we chatted about this specific feature on JabbR. |
This is a key feature. Developers should be able to find the identity of the caller in the same property regardless of host type and past/present/future Dev stack. The manipulation of claims should not be coupled to how the claims themselves were obtained, which is the promise that .net made from 4.5 onward. |
@vibronet Totally agree its just the implementation in .NET 4.5 doesn't have everything required to make this work properly. |
Really? Are we reviving that? I thought you gonna deprecate global mutable statics in favour of modern techniques like DI and better testability. Are you also planning to bring HttpContext.Current back? :p |
This is about compatibility on .NET 4.x. It's also not going to work on .NET core AFAIK. I generally hate the statics but its the pattern the identity team has been pushing. There's actually a problem with the implementation in NET 4.x that makes it hard to implement this properly thats why it's not working right now. HttpContext.Current isn't coming back as a static 😄 |
Right - as you are saying -
So why care at all in ASP.NET 5? |
@leastprivilege can you be specific as to what doesn't work reliably right now?
|
Thread.CurrentPrincipal (and thus ClaimsPrincipal.Current) comes from a time where
Both has clearly changed. There have been a couple of of inconsistencies with using Thread.CurrentPrincipal and async/await in the past - e.g. with russian doll style pipelines (e.g. Web API and I guess Katana and ASP.NET 5 have the same issue). When e.g. one piece in the pipeline sets Thread.CurrentPrincipal on the way in - on the way out plumbing that runs "later" then the code that set the principal in the first place does not see the right principal due to async/await cleaning up the call stack. This happened in Web API with a message handler that set the principal on the way in - but the media type formatter ran much later on the way out. I do remember other inconsistencies with Web API and the Katana self host where after creating a bunch of threads the current principal was not in sync anymore with the Web API request context. Generally using the request context in Web API was the "officially" recommended way of accessing the current principal. Syncing and propagating the principal to new threads seems complex and error prone. That combined with statics makes this approach a thing of the past. ASP.NET 5 is a thing of the future. my 2c. |
Mutable static state 🔫 Sure, may as well bring in CommonServiceLocator while we're at it. Sorry for the sarcastic tone but I strongly feel this is a Bad Idea. |
@leastprivilege Interesting observations, I agree with most of them. Some history. Since at the time the runtimes of interest were WCF and Asp.Net, returning Thread.CurrentPrincipal seemed the right default. It is and was my belief that the runtime that is responsible for creating the ClaimsPrincipal should be responsible for crafting the ClaimsPrincipalSelector. So conceptually, I think we are on the same page. In multi-threaded, async, apppool, queued apps, there has to be a deterministic model for mapping back to context that the call arrived. Cannot ClaimsPrincipalSelector map back to the correct CP. @lodejard suggested perhaps we are missing the API: CurrentPrincipal {set;} Any ideas you have to arrive at the correct API are welcome. |
ASP.NET 5 is DI enabled all over - the current principal should be injectable. |
Is it even possible to create a Consistent programming models are all very well and good when they make sense in all the contexts across which they are consistent, but to expect all models to be applicable across all the contexts in which C# and .NET can be used is unrealistic. |
Well the IHttpContextAccessor service already basically provides this via context.User |
@HaoK the idea was to create a selector the mimic'd IHttpContextAccessor. |
We will revisit this when an appropriate facility exists to set the current thread's principal. |
Any news on this ? |
You can get it from the |
Thanks, that works. |
You should pass in the |
What are the current best practices to get the identity of a caller in the business logic layers of an aspcore application? It seems strange to pass around the |
Why does that feel strange? It's an input to your logic, right? Making the identity an input parameter (as everything else) is the only sane way to test your code. |
I agree that ClaimsPrincipal should be injected in the business layer, even if
It worked fine. But since I migrated to Asp.net Core MVC 1.0.1, this fails with the exception
What need to be done to have IHttpContextAccessor available in the container ? |
Add the following to your services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); |
@davidfowl, @dougbu That worked. Thanks! |
I agree. I used Web API 2 on my previous project and it was quite convenient to have identity as an ambient dependency. I used asyncs a lot and did not experience mentioned problems with identity loss. On a new project I tried to apply the same pattern using ASP.NET Core and faced this issue. Yes, it is certainly possible to pass the identity as a parameter to the core, but that would only pollute the layer contract. Internally the identity is passed explicitly to sub-components when needed but this is hidden from core users. |
After all, |
@barynov then inject it as a dependency into your components. |
@davidfowl I ended up with an action filter that sets |
@nathannoble @dougbu @davidfowl
Is there any concern that the |
HttpContextAccessor does not create the HttpContext, it only stores the current one for a given request. |
AFAIK the best practice is to use HttpContext.User in the BLL layer, which also can be used in Controller classes if you need to apply the same kind of logic outside of your BLL layer. |
Could the aspnet.core framework not register an HttpContext instance into the request scope when it is created? The request scope seems to me the ideal place to register instances (singletons) that are ambient to the request handling logic. The request scope guarantees the instance is per request, and all request processing logic can access it simply through DI. IMHO using a singleton with AsyncLocal smells a lot like global mutable state. |
In previous runtimes ClaimsPrincipal.Current returned the ClaimsPrincipal that was created by the authentication layer. This provided a consistent programming model.
The text was updated successfully, but these errors were encountered: