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()?