Get Current User in a Blazor component

There are three possibilities for getting the user in a component (a page is a component):

  1. Inject IHttpContextAccessor and from it access HttpContext and then User; need to register IHttpContextAccessor in Startup.ConfigureServices, normally using AddHttpContextAccessor
  2. Inject a AuthenticationStateProvider property, call GetAuthenticationStateAsync and get User from it
  3. Wrap your component in a <CascadingAuthenticationState> component, declare a Task<AuthenticationState> property and call it to get the User (similar to #2)

See more here: https://docs.microsoft.com/en-us/aspnet/core/security/blazor.


I've now been able to get it to work with a general class, as well as a component.

To get access to the HttpContext User; in ConfigureServices, in Startup.cs add

services.AddHttpContextAccessor();

I have a CorporateUserService class for my CorporateUser class. The service class gets a DbContext through constructor injection.

I then created a new CurrentCorporateUserService that inherits from the CorporateUserService. It accepts a DbContext and an IHttpContextAccessor through constructor injection

public class CurrentCorporateUserService : CorporateUserService
{
    private readonly IHttpContextAccessor _httpContextAccessor;

    public CurrentCorporateUserService(IHttpContextAccessor httpContextAccessor,
        MyDbContext context) : base(context)
    {
        _httpContextAccessor = httpContextAccessor;
    }
    ...

The base service class has a method GetUserByUsername(string username). The Current service class adds an additional method

public CorporateUser GetCurrentUser()
{
    return base.GetUserByUsername(_httpContextAccessor.HttpContext.User.Identity.Name.Substring(8));
}

The Current service class is registered in Startup.cs

services.AddScoped<CurrentCorporateUserService>();

Once that is done, I can use the CurrentCorporateUserService in a component with directive injection.

[Inject]
private CurrentCorporateUserService CurrentCorporateUserService { get; set; } = 
default!;

or in any class, with constructor injection.

public MyDbContext(DbContextOptions<MyDbContext> options,
    CurrentCorporateUserService CurrentCorporateUserService)
    : base(options) 
{
    _currentUser = CurrentCorporateUserService.GetCurrentUser();
}

Making it a project wide service means all my developers do not have to concern themselves with how to get the Current User, they just need to inject the service into their class.

For example, using it in MyDbContext makes the current user available to every save event. In the code below, any class that inherits the BaseReport class will automatically have the report metadata updated when the record is saved.

public override Int32 SaveChanges()
{         
    var entries = ChangeTracker.Entries().Where(e => e.Entity is BaseReport
    && (e.State == EntityState.Added || e.State == EntityState.Modified));

    foreach (var entityEntry in entries)
    {
        ((BaseReport)entityEntry.Entity).ModifiedDate = DateTime.Now;
        ((BaseReport)entityEntry.Entity).ModifiedByUser = _currentUser.Username;
    }

    return base.SaveChanges();
}

I've had a similar requirement and have been using:

var authstate = await AuthenticationStateProvider.GetAuthenticationStateAsync();
var user = authstate.User;
var name = user.Identity.Name;

I already had an AuthenticationStateProvider in my startup.cs and added it to the constructor of my custom class.