using Microsoft.AspNetCore.Components.Authorization; using System.Security.Claims; using System.IdentityModel.Tokens.Jwt; namespace FinControl.Web.Services; public class AuthStateProvider : AuthenticationStateProvider { private readonly FinControlApiService _apiService; private readonly ILocalStorageService _localStorage; public AuthStateProvider(FinControlApiService apiService, ILocalStorageService localStorage) { _apiService = apiService; _localStorage = localStorage; } public override async Task GetAuthenticationStateAsync() { var token = await _localStorage.GetItemAsync("token"); if (string.IsNullOrEmpty(token)) { return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())); } try { var handler = new JwtSecurityTokenHandler(); var jwtToken = handler.ReadJwtToken(token); // Verificar se o token expirou if (jwtToken.ValidTo < DateTime.UtcNow) { await _localStorage.RemoveItemAsync("token"); return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())); } var identity = new ClaimsIdentity(jwtToken.Claims, "jwt"); var user = new ClaimsPrincipal(identity); return new AuthenticationState(user); } catch { await _localStorage.RemoveItemAsync("token"); return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())); } } public async Task Login(string email, string password) { var response = await _apiService.LoginAsync(email, password); if (response != null && !string.IsNullOrEmpty(response.Token)) { await _localStorage.SetItemAsync("token", response.Token); await _localStorage.SetItemAsync("userId", response.User.Id.ToString()); NotifyAuthenticationStateChanged(GetAuthenticationStateAsync()); } } public async Task Register(string name, string email, string password) { var response = await _apiService.RegisterAsync(name, email, password); if (response != null && !string.IsNullOrEmpty(response.Token)) { await _localStorage.SetItemAsync("token", response.Token); await _localStorage.SetItemAsync("userId", response.User.Id.ToString()); NotifyAuthenticationStateChanged(GetAuthenticationStateAsync()); } } public async Task Logout() { await _localStorage.RemoveItemAsync("token"); await _localStorage.RemoveItemAsync("userId"); NotifyAuthenticationStateChanged(GetAuthenticationStateAsync()); } public async Task GetToken() { return await _localStorage.GetItemAsync("token"); } public async Task GetUserId() { return await _localStorage.GetItemAsync("userId"); } } public interface ILocalStorageService { Task SetItemAsync(string key, string value); Task GetItemAsync(string key); Task RemoveItemAsync(string key); } public class LocalStorageService : ILocalStorageService { public async Task SetItemAsync(string key, string value) { await Task.Run(() => { // Simular localStorage - em produção usar Blazored.LocalStorage var dict = GetStorage(); dict[key] = value; }); } public async Task GetItemAsync(string key) { return await Task.Run(() => { var dict = GetStorage(); return dict.ContainsKey(key) ? dict[key] : null; }); } public async Task RemoveItemAsync(string key) { await Task.Run(() => { var dict = GetStorage(); dict.Remove(key); }); } private static Dictionary GetStorage() { // Nota: Esta é uma implementação simples para demo // Em produção, usar: https://github.com/Blazored/LocalStorage if (!AppData.Storage.ContainsKey("localStorage")) { AppData.Storage["localStorage"] = new Dictionary(); } return (Dictionary)AppData.Storage["localStorage"]; } } // Storage em memória (apenas para demo - será perdido ao recarregar) public static class AppData { public static Dictionary Storage { get; } = new(); } public class LoginResponse { public string? Token { get; set; } public UserInfo? User { get; set; } } public class UserInfo { public Guid Id { get; set; } public string? Name { get; set; } public string? Email { get; set; } }