using System.Security.Claims; using Microsoft.AspNetCore.Components.Authorization; using Microsoft.AspNetCore.Components.Server; using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Options; namespace BuchhaltungBlazor.Areas.Identity; public class RevalidatingIdentityAuthenticationStateProvider : RevalidatingServerAuthenticationStateProvider where TUser : class { private readonly IdentityOptions _options; private readonly IServiceScopeFactory _scopeFactory; public RevalidatingIdentityAuthenticationStateProvider(ILoggerFactory loggerFactory, IServiceScopeFactory scopeFactory, IOptions optionsAccessor) : base(loggerFactory) { _scopeFactory = scopeFactory; _options = optionsAccessor.Value; } protected override TimeSpan RevalidationInterval => TimeSpan.FromMinutes(30); protected override async Task ValidateAuthenticationStateAsync(AuthenticationState authenticationState, CancellationToken cancellationToken) { // Get the user manager from a new scope to ensure it fetches fresh data IServiceScope? scope = _scopeFactory.CreateScope(); try { UserManager? userManager = scope.ServiceProvider.GetRequiredService>(); return await ValidateSecurityStampAsync(userManager, authenticationState.User); } finally { if (scope is IAsyncDisposable asyncDisposable) await asyncDisposable.DisposeAsync(); else scope.Dispose(); } } private async Task ValidateSecurityStampAsync(UserManager userManager, ClaimsPrincipal principal) { TUser? user = await userManager.GetUserAsync(principal); if (user == null) return false; if (!userManager.SupportsUserSecurityStamp) return true; string? principalStamp = principal.FindFirstValue(_options.ClaimsIdentity.SecurityStampClaimType); string? userStamp = await userManager.GetSecurityStampAsync(user); return principalStamp == userStamp; } }