I'm starting a new site with Blazor and Windows Authentication and need to identify the current user viewing the page/component.
For a Razor Page, the current user name can be accessed with Context.User.Identity.Name
, but that doesn't seem to work in a Blazor component. I've tried injecting HttpContext into the component but the Context is null at runtime.
As a bonus, I will eventually want to incorporate this into Startup.cs so I only need to get the username once and can leverage a corporate user class (with EF Core) for my applications. Answers tailored to that use case would also be appreciated.
There are three possibilities for getting the user in a component (a page is a component): Inject IHttpContextAccessor and from it access HttpContext and then User ; need to register IHttpContextAccessor in Startup. ConfigureServices , normally using AddHttpContextAccessor .
You can get the current page title in Blazor by using the “title” property of the document object in JavaScript and by using a . JavaScript interop since there is no DOM accessibility in Blazor.
To capture a component reference in Blazor, use the @ref directive attribute. The value of the attribute should match the name of a settable field with the same type as the referenced component. When the parent component is rendered, the field is populated with the child component instance.
Begin by creating a new Blazor Server App project in Visual Studio. Then right click on the Pages folder and select Add New Item menu option. Add a new Razor Component named Message. razor to the Pages folder.
There are three possibilities for getting the user in a component (a page is a component):
IHttpContextAccessor
and from it access HttpContext
and then User
; need to register IHttpContextAccessor
in Startup.ConfigureServices
, normally using AddHttpContextAccessor
. Edit: according to the Microsoft docs you must not do this for security reasons.AuthenticationStateProvider
property, call GetAuthenticationStateAsync
and get a User
from it<CascadingAuthenticationState>
component, declare a Task<AuthenticationState>
property and call it to get the User
(similar to #2)See more here: https://learn.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();
}
For me the solution mentioned in the first answer 2. option worked perfect: I am using Blazor server side on .Net Core 5.0 . I injected
@inject AuthenticationStateProvider GetAuthenticationStateAsync
in my Blazor page and added the following in the code section:
protected async override Task OnInitializedAsync()
{
var authstate = await GetAuthenticationStateAsync.GetAuthenticationStateAsync();
var user = authstate.User;
var name = user.Identity.Name;
}
In my startup.cs, I have the following lines:
services.AddScoped<ApiAuthenticationStateProvider>();
services.AddScoped<AuthenticationStateProvider>(p =>
p.GetRequiredService<ApiAuthenticationStateProvider>());
For blazor wasm
in net 5.0
and above. Here is how I did,
<App>
component inside <CascadingAuthenticationState>
as shown below,<CascadingAuthenticationState>
<Router AppAssembly="@typeof(Program).Assembly">
<Found Context="routeData">
...
</Found>
<NotFound>
...
</NotFound>
</Router>
</CascadingAuthenticationState>
Task<AuthenticationState>
CascadingParameter
inside any component as shown below,public class AppRootBase : ComponentBase
{
[CascadingParameter] private Task<AuthenticationState> authenticationStateTask { get; set; }
}
Identity
and Claims
inside component as shown below,protected override async Task OnInitializedAsync()
{
var authState = await authenticationStateTask;
var user = authState.User;
if (user.Identity.IsAuthenticated)
{
Console.WriteLine($"{user.Identity.Name} is authenticated.");
}
}
Here is the reference from Microsoft docs.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With