I am using the exemplary authentication which is generated when creating a new Blazor Web App. I solved the problem in the meantime myself.
I had to augment UserInfo
in the Client project:
public class UserInfo {
public required string UserName { get; set; } // <= added
public required string UserId { get; set; }
public required string Email { get; set; }
public string? Role { get; set; } // <= added
}
And PersistingRevalidatingAuthenticationStateProvider
in the server-side project:
if(principal.Identity?.IsAuthenticated == true) {
var userId = principal.FindFirst(_options.ClaimsIdentity.UserIdClaimType)?.Value;
var email = principal.FindFirst(_options.ClaimsIdentity.EmailClaimType)?.Value;
// The next two ones are added
var name = principal.FindFirst(_options.ClaimsIdentity.UserNameClaimType)?.Value;
var role = principal.FindFirst(_options.ClaimsIdentity.RoleClaimType)?.Value;
if(userId != null && email != null) {
_state.PersistAsJson(nameof(UserInfo), new UserInfo {
UserId = userId,
Email = email,
// New below
UserName = name ?? email,
Role = role
});
}
}
And PersistentAuthenticationStateProvider
on the client:
public override Task<AuthenticationState> GetAuthenticationStateAsync() {
if(!persistentState.TryTakeFromJson<UserInfo>(nameof(UserInfo), out var userInfo) || userInfo is null) {
return _unauthenticatedTask;
}
IEnumerable<Claim> EnumerateClaims() {
yield return new(ClaimTypes.NameIdentifier, userInfo.UserId);
yield return new(ClaimTypes.Name, userInfo.UserName); // added
yield return new(ClaimTypes.Email, userInfo.Email);
// added
if(userInfo.Role is string role) {
yield return new(ClaimTypes.Role, role);
}
}
return Task.FromResult(
new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(EnumerateClaims(),
authenticationType: nameof(PersistentAuthenticationStateProvider)))));
}
This allows me to get the real user name and role.