I have retrieved the userId in a Blazor component using the code below: [CascadingParameter] public Task AuthenticationStateTask { get; set; }
protected override async Task OnInitializedAsync()
{
YoogieContext cxt = new YoogieContext();
var authState = await AuthenticationStateTask;
var user = authState.User;
var UserStringId = user.FindFirst(c => c.Type.Contains("nameidentifier"))?.Value;
}
How do I get the userId from a code behind (.cs) file? Using Blazor Server.
The cascaded Task<AuthenticationStateTask>
is derived from the AuthenticationStateProvider
so you might as well use it in code behind classes. You have to use it in service classes, there's no cacaded value to access.
The advantage of dropping back to the underlying AuthenticationStateProvider
is you get access to the identity change events, so can react when the identity changes.
Here's a simple service to demonstrate interacting with the AuthenticationStateProvider:
public class MyIdentityService : IDisposable
{
private AuthenticationStateProvider _authenticationStateProvider;
public event EventHandler<IdentityChangedEventArgs>? IdentityChanged;
public MyIdentityService(AuthenticationStateProvider authenticationStateProvider)
{
// The dependancy container will inject it's AuthenticationStateProvider instance here
_authenticationStateProvider = authenticationStateProvider;
// register for the state changed event
_authenticationStateProvider.AuthenticationStateChanged += NotifyIdentityChanged;
}
// Method to get the current Identity
public async ValueTask<ClaimsPrincipal> GetCurrentIdentity()
{
AuthenticationState state = await _authenticationStateProvider.GetAuthenticationStateAsync();
return state.User;
}
// Fire and forget async event handler that waits on the Task completion before invoking the Event
private async void NotifyIdentityChanged(Task<AuthenticationState> newAuthStateTask)
{
AuthenticationState state = await newAuthStateTask;
this.IdentityChanged?.Invoke(null, new() { Identity = state.User});
}
// de-register for the state changed event
public void Dispose()
=> _authenticationStateProvider.AuthenticationStateChanged -= NotifyIdentityChanged;
}
// Custom Event Args class to pass the new identity
public class IdentityChangedEventArgs : EventArgs
{
public ClaimsPrincipal Identity { get; init; } = new ClaimsPrincipal();
}
registered in Program:
builder.Services.AddSingleton<WeatherForecastService>();
builder.Services.AddScoped<MyIdentityService>();
My Index.razor
@page "/"
<PageTitle>Index</PageTitle>
<h1>Hello, world!</h1>
Welcome to your new app.
<SurveyPrompt Title="How is Blazor working for you?" />
<div class="alert alert-info">
Identity 1: @(this.Identity1.Identity?.Name ?? "No User Logged In")
</div>
<div class="alert alert-success">
Identity 2: @(this.Identity2.Identity?.Name ?? "No User Logged In")
</div>
And a code behind file that shows using the AuthenticationStateProvider
directly and the MyIdentityService
.
public partial class Index : ComponentBase, IDisposable
{
private ClaimsPrincipal Identity1 = new ClaimsPrincipal();
private ClaimsPrincipal Identity2 = new ClaimsPrincipal();
[Inject] private AuthenticationStateProvider _authenticationStateProvider { get; set; } = default!;
[Inject] private MyIdentityService _myService { get; set; } = default!;
protected async override Task OnInitializedAsync()
{
AuthenticationState state = await _authenticationStateProvider.GetAuthenticationStateAsync();
Identity1 = state.User;
_authenticationStateProvider.AuthenticationStateChanged += OnAuthenticationStateChanged;
Identity2 = await _myService.GetCurrentIdentity();
this._myService.IdentityChanged += OnIdentityChanged;
}
private async void OnAuthenticationStateChanged(Task<AuthenticationState> newAuthStateTask)
{
AuthenticationState state = await newAuthStateTask;
Identity1 = state.User;
// if you want to update the component when the identity changes
await this.InvokeAsync(StateHasChanged);
}
private async void OnIdentityChanged(object? sender, IdentityChangedEventArgs e)
{
Identity2 = e.Identity;
// if you want to update the component when the identity changes
await this.InvokeAsync(StateHasChanged);
}
public void Dispose()
{
_authenticationStateProvider.AuthenticationStateChanged -= OnAuthenticationStateChanged;
this._myService.IdentityChanged -= OnIdentityChanged;
}
}
Here's my test page - I've used Windows authentication for simplicity.