using Microsoft.AspNetCore.Components.Authorization; using Microsoft.JSInterop; using System.Net.Http.Headers; using System.Security.Claims; using System.Text.Json; using phronCare.UIBlazor.Extensions; namespace phronCare.UIBlazor.Services.Authorization { public class CustomAuthorizationProvider: AuthenticationStateProvider,ILoginService { private readonly IJSExtensions js; private readonly HttpClient httpClient; public static readonly string TOKENKEY = "phronCareTokenKey"; private AuthenticationState Anonimo => new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())); public CustomAuthorizationProvider(IJSRuntime _js, HttpClient httpClient) //Constructor { this.httpClient = httpClient; js = new IJSExtensions(_js); } public async override Task GetAuthenticationStateAsync() { var token = await js.GetFromLocalStorage(TOKENKEY); if (string.IsNullOrEmpty(token)) { return Anonimo; } return BuildAuthenticationState(token); } private AuthenticationState BuildAuthenticationState(string token) { httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(ParseClaimsFromJwt(token), "jwt"))); } public async Task GetTokenData() { var token = await js.GetFromLocalStorage(TOKENKEY); //TokenData result = JsonSerializer.Deserialize(token); //return result; TokenData? result = JsonSerializer.Deserialize(token); if (result == null) { // Maneja el caso en el que la deserialización falla y devuelve null // Puedes lanzar una excepción, retornar un valor predeterminado, o manejar el error de otra forma throw new InvalidOperationException("El token no se pudo deserializar en un objeto TokenData."); } return result; } public async Task Login(string token) { await js.RemoveItem(TOKENKEY); await js.SetInLocalStorage(TOKENKEY, token); var authState = BuildAuthenticationState(token); NotifyAuthenticationStateChanged(Task.FromResult(authState)); } public async Task Logout() { httpClient.DefaultRequestHeaders.Authorization = null; await js.RemoveItem(TOKENKEY); NotifyAuthenticationStateChanged(Task.FromResult(Anonimo)); } //private IEnumerable ParseClaimsFromJwt(string jwt) //{ // var claims = new List(); // var payload = jwt.Split('.')[1]; // var jsonBytes = ParseBase64WithoutPadding(payload); // var keyValuePairs = JsonSerializer.Deserialize>(jsonBytes); // keyValuePairs.TryGetValue(ClaimTypes.Role, out object roles); // if (roles != null) // { // if (roles.ToString().Trim().StartsWith("[")) // { // var parsedRoles = JsonSerializer.Deserialize(roles.ToString()); // foreach (var parsedRole in parsedRoles) // { // claims.Add(new Claim(ClaimTypes.Role, parsedRole)); // } // } // else // { // claims.Add(new Claim(ClaimTypes.Role, roles.ToString())); // } // keyValuePairs.Remove(ClaimTypes.Role); // } // claims.AddRange(keyValuePairs.Select(kvp => new Claim(kvp.Key, kvp.Value.ToString()))); // return claims; //} private IEnumerable ParseClaimsFromJwt(string jwt) { var claims = new List(); var payload = jwt.Split('.')[1]; var jsonBytes = ParseBase64WithoutPadding(payload); var keyValuePairs = JsonSerializer.Deserialize>(jsonBytes); if (keyValuePairs != null && keyValuePairs.TryGetValue(ClaimTypes.Role, out object roles)) { // Verificamos si roles no es null y lo convertimos a string de manera segura string rolesString = roles?.ToString() ?? string.Empty; // Aquí usamos un valor por defecto si es null if (!string.IsNullOrEmpty(rolesString)) { if (rolesString.Trim().StartsWith("[")) { var parsedRoles = JsonSerializer.Deserialize(rolesString) ?? Array.Empty(); foreach (var parsedRole in parsedRoles) { claims.Add(new Claim(ClaimTypes.Role, parsedRole)); } } else { claims.Add(new Claim(ClaimTypes.Role, rolesString)); } } keyValuePairs.Remove(ClaimTypes.Role); } if (keyValuePairs != null) { claims.AddRange(keyValuePairs.Select(kvp => new Claim(kvp.Key, kvp.Value?.ToString() ?? "defaultValue"))); } return claims; } private byte[] ParseBase64WithoutPadding(string base64) { switch (base64.Length % 4) { case 2: base64 += "=="; break; case 3: base64 += "="; break; } return Convert.FromBase64String(base64); } public class TokenData { public string userName { get; set; } = string.Empty; public string token { get; set; } = string.Empty; public string role { get; set; } = string.Empty; public DateTime expiryTimeStamp { get; set; } } } }