I recently had a requirement where I want to add Custom Claims to the current user in a Blazor Web Application. I used IClaimsTransformation, but it doesn't work with Blazor. Instead, the correct option for Blazor is to implement a custom AuthenticationStateProvider.
public class ApplicationAuthenticationStateProvider : AuthenticationStateProvider
{
private readonly AuthenticationStateProvider _authenticationStateProvider;
private readonly IUserService _userService;
public ApplicationAuthenticationStateProvider(AuthenticationStateProvider AuthenticationStateProvider, IUserService userService)
{
_authenticationStateProvider = AuthenticationStateProvider;
_userService = userService;
}
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
AuthenticationState authenticationState = await _authenticationStateProvider.GetAuthenticationStateAsync();
if (authenticationState.User.Identity?.IsAuthenticated != true)
{
return authenticationState;
}
// Check if user already has the UserId claim
if (authenticationState.User.HasClaim(x => x.Type == ApplicationClaimTypes.UserId))
{
return authenticationState;
}
// TODO: Get the user from the database using current claims and IUserService
string applicationUserId = "someUserId";
ClaimsIdentity claimsIdentity = new ClaimsIdentity();
claimsIdentity.AddClaim(new Claim(ApplicationClaimTypes.UserId, applicationUserId));
authenticationState.User.AddIdentity(claimsIdentity);
return authenticationState;
}
}
Register ApplicationAuthenticationStateProvider,
builder.Services.AddScoped<ApplicationAuthenticationStateProvider>();
Use,
// This is some service where you want to use authenticationState
public class BlazorIdentityService : IIdentityService
{
private readonly ApplicationAuthenticationStateProvider _applicationAuthenticationStateProvider;
public BlazorIdentityService(ApplicationAuthenticationStateProvider applicationAuthenticationStateProvider)
{
_applicationAuthenticationStateProvider = applicationAuthenticationStateProvider;
}
public async Task<string> GetCurrentUserId()
{
AuthenticationState authenticationState = await _applicationAuthenticationStateProvider?.GetAuthenticationStateAsync();
return authenticationState.User?.Claims?.SingleOrDefault(x => x.Type == ApplicationClaimTypes.UserId)?.Value;
}
}
Hope this helps.
Happy Coding.