Thread.CurrentPrincipal was useful - alternatives? #27608
-
Hey, I realise ASP.NET Core has switched to a different identity model and Thread.CurrentPrincipal is obsolete. I’m otherwise an avid user of DI. I’m finding the new system to be a bit cumbersome, here are some issues:
I’ve achieved this by instead injecting IUserSession service I made that has a User property, and this interface uses HttpContextAccessor to grab the principal Id claim and load a User object from the database.
In the past, a temporary change in Thread.CurrentPrincipal would flow properly and feel very natural:
|
Beta Was this translation helpful? Give feedback.
Replies: 3 comments 1 reply
-
as far as I understood, you dont want to use the default written package. so i skip this. |
Beta Was this translation helpful? Give feedback.
-
Thread.Current falls apart in multi-threading and async scenarios and history has shown relying on it has lead to security vulnerabilities. So, it's gone away and forcing you to flow a user provides a safer framework for user security. Is there any post-auth point I can set Thread.CurrentPrincipal to my hydrated User object? This seems to be your key problem. You can either enhance it during login, before its persisted, or, with utter sadness, you can do it on every request, which doesn't scale, because now you have database queries on every request. How you enhance depends on how you're logging in. Identity you can do in code for the login (and then inside the cooke refresh) but claims transformation is probably the most portable. Impersonation is a loaded term, and so it really depends on how you are using and sending identities off to other components or systems. |
Beta Was this translation helpful? Give feedback.
-
FWIW, With that in mind, you can write a middleware registered after the authentication middleware that sets it for the rest of the request. You could also use Something like: app.UseAuthentication();
app.UseAuthorization();
app.Use(next => async context =>
{
var principal = Thread.CurrentPrincipal;
// Use the principal resolved from the default authentication scheme handler.
// You can also use context.AuthenticateAsync("scheme") to pick a different principal.
Thread.CurrentPrincipal = context.User;
try
{
await next(context);
}
finally
{
Thread.CurrentPrincipal = principal;
}
}); |
Beta Was this translation helpful? Give feedback.
FWIW,
Thread.CurrentPrincipal
is backed by anAsyncLocal<IPrincipal>
instance on .NET Core, so it will work nicely withasync
/await
and context switching: https://source.dot.net/#System.Private.CoreLib/Thread.cs,137With that in mind, you can write a middleware registered after the authentication middleware that sets it for the rest of the request. You could also use
ClaimsPrincipal.Current
and setClaimsPrincipal.ClaimsPrincipalSelector
to resolve it from wherever you want.Something like: