Making HttpContext.User available to 3rd party code without Microsoft.AspNetCore.Http dependency
- Dominant language
- C#
- Stars
- 38.4k
- Forks
- 10.9k
- Avg merge
- 2d 5h
- Merged PRs (30d)
- 276
Description
## Background and Motivation
On AspNetCore, when you need to access the `HttpContext` in a "service" class, you use an `IHttpContextAccessor` to get the thread-safe instance of the `HttpContext` used by the current thread, thanks to its internal use of `AsyncLocal`.
However, if you need to be able to access the `HttpContext.User`, AND the service class is in another assembly, you can no longer rely on `ClaimsPrincipal.Current` or `Thread.CurrentPrincipal` to get you that information. If you control the external assembly, you're now dependent on `Microsoft.AspNetCore.Http` in all of your libraries, which is unnecessary.
## Proposed API
The proposal is a stand-alone class that does not affect the behavior or functionality of any existing APIs, which should make it quick to approve and get into the current release, even given the current timeframe for .NET 6's release.
The solution is to implement an identical pattern to `IHttpContextAccessor` for `IPrincipal`. This will require an Interface to be added to `System.Security`, and an `HttpContextPrincipalAccessor` in `Microsoft.AspNetCore.Http`.
```diff
namespace Microsoft.AspNetCore.Authentication
{
public class AuthenticationOptions
{
+ bool EnableThreadCurrentPrincipal { get; set; }
}
}
```
Because the shipped implementation takes an `IHttpContextAccessor` in the constructor, it will pull in the thread's `HttpContext` to correctly pull the user from.
## Usage Examples
``` C#
public class Startup
{
public void ConfigureServices(IServiceCollection services)
{
services
.AddAuthentication(options =>
{
options.EnableThreadCurrentPrincipal = true;
options.DefaultScheme = "Cookies";
});
}
}
```
## Alternative Designs
- I considered making everything a `ClaimsPrincipal`, as that is the proper way to do things, but I considered that it could be a `WindowsPrincipal` instead, so `IPrincipal` is probably a better approach.
- The implementation would probably do a `TryAddService()` on `IHttpContextAccessor`, just in case the user forgot to add one.
## Risks
- AFAIK there are no risks to the added API itself, just the timing.
- The `IPrincipalAccessor` API would need to get in the .NET Core Libraries, which risks the team not wanting to add it at this stage of the game.
- The AspNetCore team may decide not to add the `HttpContextPrincipalAccessor` at this stage of the game, even if the .NET Core team is cool with it.
I have the requisite pull requests ready to submit if the team is OK with this.
Contributor guide
Assessment
This issue has not been assessed yet.