In this article, we are going to see different ways to get the currently authenticated user using claims in ASP.NET Core. The code for this article is based on the respective code from the article on Authentication with ASP.NET Core Web API.
Let’s start.
Getting the Current User With Claims in Controllers
Claims-based identity is a way to keep information about a user. A claim is a key-value pair that is assigned to a user by a trusted source. A claim defines what the user is, in contrast to what the user can do. An identity can contain multiple claims; examples are the user’s id, name, and email, to name but a few.
Inside a controller, we can directly access the User
property, which is of type ClaimsPrincipal
.
Let’s use this object in order to get the claims it contains:
[HttpGet, Authorize] public IEnumerable<string> Get() { Console.WriteLine("User Id: " + User.FindFirstValue(ClaimTypes.NameIdentifier)); Console.WriteLine("Username: " + User.FindFirstValue(ClaimTypes.Name)); Console.WriteLine("Role: " + User.FindFirstValue(ClaimTypes.Role)); Console.WriteLine("First name: " + User.FindFirstValue("firstname")); Console.WriteLine("Last name: " + User.FindFirstValue("lastname")); return _service.GetCustomers(); }
Note that we can also get the custom claims that we have defined, i.e. claims that provide the first and last name of the user.
However, there is a catch. Let’s try to get the current user inside the Controller’s constructor:
public class CustomersController : ControllerBase { private readonly ICustomerService _service; public CustomersController(ICustomerService service) { _service = service; Console.WriteLine("User Id: " + User.FindFirstValue(ClaimTypes.NameIdentifier)); Console.WriteLine("Username: " + User.FindFirstValue(ClaimTypes.Name)); } ... }
As a result, we realize that the User
property inside the constructor is null
. Fortunately, there is a way to get the User
property here, by injecting an object that implements the IHttpContextAccessor
interface:
public class CustomersController : ControllerBase { private readonly IHttpContextAccessor _httpContextAccessor; private readonly ICustomerService _service; public CustomersController(IHttpContextAccessor httpContextAccessor, ICustomerService service) { _httpContextAccessor = httpContextAccessor; _service = service; Console.WriteLine("User Id: " + _httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.NameIdentifier)); Console.WriteLine("Username: " + _httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.Name)); } ... }
Through the IHttpContextAccessor
interface, we can get the HttpContext
object and from there we are able to access the User
object and its claims.
Finally, let’s instruct the Program
class to make IHttpContextAccessor
available to our classes:
builder.Services.AddHttpContextAccessor();
Getting the Current User With Claims in Other Classes
Let’s consider the case of the CustomersService
class, where we need to get information about the current user. Since we are not inside a controller, we do not have direct access to the User
property:
public class CustomerService: ICustomerService { private readonly IHttpContextAccessor _httpContextAccessor; public CustomerService(IHttpContextAccessor httpContextAccessor) { _httpContextAccessor = httpContextAccessor; } public IEnumerable<string> GetCustomers() { Console.WriteLine("User Id: " + _httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.NameIdentifier)); Console.WriteLine("Username: " + _httpContextAccessor.HttpContext?.User.FindFirstValue(ClaimTypes.Name)); return new string[] { "John Doe", "Jane Doe" }; } }
Luckily, we solve the issue inject by injecting an IHttpContextAccessor
object into the service and get the claims of the current user.
Conclusion
In this article, we have seen how we may get the current user, in various parts of our web application (controllers and other classes).