Friday, November 29, 2024

Blazor Web App: Adding Custom Claims to Current User

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.

Regards,
Jaliya

No comments:

Post a Comment