using System.Security.Claims; using Microsoft.AspNetCore.Components.Authorization; namespace ChessCubing.App.Services; public sealed class UserSession(AuthenticationStateProvider authenticationStateProvider) { public async ValueTask GetStorageScopeAsync() { var authState = await authenticationStateProvider.GetAuthenticationStateAsync(); var userId = ResolveUserId(authState.User); return new UserStorageScope( $"{MatchStore.StorageKeyPrefix}:{userId}", $"{MatchStore.WindowNameKeyPrefix}:{userId}:"); } private static string ResolveUserId(ClaimsPrincipal user) { if (user.Identity?.IsAuthenticated != true) { return "anonymous"; } var rawIdentifier = user.FindFirst("sub")?.Value ?? user.FindFirst(ClaimTypes.NameIdentifier)?.Value ?? user.FindFirst("preferred_username")?.Value ?? user.Identity?.Name; if (string.IsNullOrWhiteSpace(rawIdentifier)) { return "authenticated"; } return Uri.EscapeDataString(rawIdentifier.Trim()); } } public readonly record struct UserStorageScope(string StorageKey, string WindowNameKey);