Quantcast
Channel: Active questions tagged blazor - Stack Overflow
Viewing all articles
Browse latest Browse all 4839

Blazor Server AuthenticationStateProvider

$
0
0

I have Blazor server app, (built using the .NET7 Blazor server template, upgraded to .NET8 in place). I want to trigger my code on AuthenticationStateChanged.In program.cs, I have this line (which I think came from the original template):

builder.Services.AddScoped<AuthenticationStateProvider, RevalidatingIdentityAuthenticationStateProvider<IdentityUser>>();

In my MainLayout.razor, I want to run code on login state changed. I have the following code:

@inject AuthenticationStateProvider authProviderprivate async void AuthStateChanged(Task<AuthenticationState> authStateTask){    var authState = await authStateTask;    if (authState != null)    {        if (authState.User.Identity.IsAuthenticated)        {            licenseService.LoadLicense(); //call the license service to set license.        }    }}protected override async Task OnInitializedAsync(){    authProvider.AuthenticationStateChanged += AuthStateChanged;    AppState.MenuChanged += ChangeState; //event fired in AppState    settings = await DataService.GetSettings();    AppState.ClinicName = settings?.ClinicName??"KFA Dental";}

and from the template:

public class RevalidatingIdentityAuthenticationStateProvider<TUser>    : RevalidatingServerAuthenticationStateProvider where TUser : class{    private readonly IServiceScopeFactory _scopeFactory;    private readonly IdentityOptions _options;    public RevalidatingIdentityAuthenticationStateProvider(        ILoggerFactory loggerFactory,        IServiceScopeFactory scopeFactory,        IOptions<IdentityOptions> optionsAccessor)        : base(loggerFactory)    {        _scopeFactory = scopeFactory;        _options = optionsAccessor.Value;    }    protected override TimeSpan RevalidationInterval => TimeSpan.FromMinutes(30);    protected override async Task<bool> ValidateAuthenticationStateAsync(        AuthenticationState authenticationState, CancellationToken cancellationToken)    {        // Get the user manager from a new scope to ensure it fetches fresh data        var scope = _scopeFactory.CreateScope();        try        {            var userManager = scope.ServiceProvider.GetRequiredService<UserManager<TUser>>();            return await ValidateSecurityStampAsync(userManager, authenticationState.User);        }        finally        {            if (scope is IAsyncDisposable asyncDisposable)            {                await asyncDisposable.DisposeAsync();            }            else            {                scope.Dispose();            }        }    }    private async Task<bool> ValidateSecurityStampAsync(UserManager<TUser> userManager, ClaimsPrincipal principal)    {        var user = await userManager.GetUserAsync(principal);        if (user == null)        {            return false;        }        else if (!userManager.SupportsUserSecurityStamp)        {            return true;        }        else        {            var principalStamp = principal.FindFirstValue(_options.ClaimsIdentity.SecurityStampClaimType);            var userStamp = await userManager.GetSecurityStampAsync(user);            return principalStamp == userStamp;        }    }    public override Task<AuthenticationState> GetAuthenticationStateAsync()    {        var identity = new ClaimsIdentity();        var user = new ClaimsPrincipal(identity);        return Task.FromResult(new AuthenticationState(user));    }    public void AuthenticateUser(string userIdentifier)    {        var identity = new ClaimsIdentity(        [            new Claim(ClaimTypes.Name, userIdentifier),    ], "Custom Authentication");        var user = new ClaimsPrincipal(identity);        NotifyAuthenticationStateChanged(            Task.FromResult(new AuthenticationState(user)));    }}

The problem is that AuthStateChanged() is not firing. Do I need to make any changes in the RevalidatingIdentityAuthenticationStateProvider()?


Viewing all articles
Browse latest Browse all 4839

Trending Articles