0

In my HomeController I can perfectly access the ClaimsPrincipal, however using a static class it doesn't seem to be possible. How can I retrieve the ClaimsHelper?

public static class ClaimsHelper
{
    public static List<Claim> GetCurrentUser()
    {
        return System.Security.Claims.ClaimsPrincipal.Current.Claims.ToList();
    }
}
Jay
  • 189
  • 4
  • 12
  • You can't, because `static` methods don't have access to the `HttpContext` unless they're passed-in as parameters. Before ASP.NET Core there was `HttpContext.Current` which worked using thread-local-storage - which means there's an (unnecessary) dependency between the current thread and your ASP.NET request. So the fix is to make `HttpContext` a parameter. – Dai Oct 01 '21 at 20:23
  • `ClaimsPrincipal.Current` is (by default) just forwards to `Thread.CurrentPrincipal` - which (surprise-surprise) uses thread-local-storage too - so just avoid those style of APIs - they are not long for this world. – Dai Oct 01 '21 at 20:24
  • I'd suggest to do it the "DI style": Name your class `IdentityService` and require the `IHttpContextAccessor`, s.a. https://stackoverflow.com/questions/36641338/how-to-get-current-user-in-asp-net-core – Christoph Lütjen Oct 01 '21 at 20:30

2 Answers2

2

You can write an extension method for your need and use it in your actions

public static class HttpContextExtensions
{


    public static ClaimsPrincipal GetClaimsPrincipal(this HttpContext httpContext)
    {
        var principal = httpContext.User as ClaimsPrincipal;
        return principal;
    }

}

and then use it in your actions:

[HttpGet]
public IActionResult Index ()
{
    var user = HttpContext.GetClaimsPrincipal();

    return Ok(user);
}

or you can use another way like this:

services.AddTransient<ClaimsPrincipal>(s =>
s.GetService<IHttpContextAccessor>().HttpContext.User);

Ref: Getting the ClaimsPrincipal in a logic layer in an aspnet core 1 application

or another way using DI just add IHttpContextAccessor then inject it to your helper class then register your helper class as a singleton service.

mohammadreza
  • 158
  • 12
  • Two questions 1) When is your code exactly using that Static Class? 2) So if I understand correctly, there is no way to retrieve the Claims in a Static Class? What if I would write a ClaimsHelper or Utilities class, (helpers and utilities are always expected to be Static). I'm not sure whether having that logic in the controller is the best fit. Do you have any suggestions? – Jay Oct 01 '21 at 21:33
  • @Jay It sounds like you're unfamiliar with how C# Extension Methods work. I suggest you research and understand that first before continuing. – Dai Oct 02 '21 at 00:55
  • please read this [link](https://learn.microsoft.com/en-us/dotnet/csharp/programming-guide/classes-and-structs/extension-methods) extension method in c# – mohammadreza Oct 03 '21 at 09:02
0

Though what the answer above does will work, I am not sure it's handling the use case you want. It seems you just need to have a variable in the static class that is the httpcontext. Then you can access it like you would anywhere else. Note, this is generally a poor pattern filled with landmines since you could be passing the context all over the place, but it does work. This should do it, but I have not yet tested.

public static class ClaimsHelper
{
    public static List<Claim> GetCurrentUser(HttpContext context)
    {
        return context.User.Claims.ToList();
    }
}

Inside a controller, you would call it like this:

public IActionResult Index ()
{
    var ctx = HttpContext.Current;
    var claims = ClaimsHelper.GetCurrentUser(ctx);
    ...
}
Ben Matthews
  • 499
  • 2
  • 5