Patch JWT
All checks were successful
CI/CD Pipeline / Build and Deploy with Docker Compose (push) Successful in 5m47s

This commit is contained in:
Leandro Hernan Rojas 2025-04-28 18:43:59 -03:00
parent bba48a7e28
commit c80da65dac
3 changed files with 54 additions and 47 deletions

View File

@ -15,7 +15,7 @@ namespace phronCare.API.Controllers
[HttpGet("empleados")] [HttpGet("empleados")]
public IEnumerable<string> GetEmpleados() public IEnumerable<string> GetEmpleados()
{ {
return new List<string> { "Leandro", "Griselda", "Agustin","Victoria" }; return new List<string> { "SOS USUARIO", "Griselda", "Agustin","Victoria" };
} }
[Authorize (Roles ="Admin")] [Authorize (Roles ="Admin")]
@ -23,7 +23,7 @@ namespace phronCare.API.Controllers
public IEnumerable<string> GetAdministradores() public IEnumerable<string> GetAdministradores()
{ {
return new List<string> { "Leandro", "Griselda", "Agustin", "Victoria" }; return new List<string> { "SOS ADMINISTRADOR", "Griselda", "Agustin", "Victoria" };
} }
} }
} }

View File

@ -69,6 +69,7 @@ else
try try
{ {
var response = await _httpClient.GetAsync("/api/Account/GetAllUsers"); var response = await _httpClient.GetAsync("/api/Account/GetAllUsers");
Console.WriteLine(token.token);
if (response.IsSuccessStatusCode) if (response.IsSuccessStatusCode)
{ {
var jsonResponse = await response.Content.ReadAsStringAsync(); var jsonResponse = await response.Content.ReadAsStringAsync();

View File

@ -7,47 +7,72 @@ using phronCare.UIBlazor.Extensions;
namespace phronCare.UIBlazor.Services.Authorization namespace phronCare.UIBlazor.Services.Authorization
{ {
public class CustomAuthorizationProvider: AuthenticationStateProvider,ILoginService public class CustomAuthorizationProvider : AuthenticationStateProvider, ILoginService
{ {
private readonly IJSExtensions js; private readonly IJSExtensions js;
private readonly HttpClient httpClient; private readonly HttpClient httpClient;
public static readonly string TOKENKEY = "phronCareTokenKey"; public static readonly string TOKENKEY = "phronCareTokenKey";
private AuthenticationState Anonimo => new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())); private AuthenticationState Anonimo => new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
public CustomAuthorizationProvider(IJSRuntime _js, HttpClient httpClient) //Constructor
public CustomAuthorizationProvider(IJSRuntime _js, HttpClient httpClient)
{ {
this.httpClient = httpClient; this.httpClient = httpClient;
js = new IJSExtensions(_js); js = new IJSExtensions(_js);
} }
public async override Task<AuthenticationState> GetAuthenticationStateAsync()
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{ {
var token = await js.GetFromLocalStorage(TOKENKEY); var token = await js.GetFromLocalStorage(TOKENKEY);
if (string.IsNullOrEmpty(token))
if (string.IsNullOrWhiteSpace(token) || !IsJwtFormat(token))
{ {
await js.RemoveItem(TOKENKEY);
return Anonimo; return Anonimo;
} }
return BuildAuthenticationState(token); return BuildAuthenticationState(token);
} }
private AuthenticationState BuildAuthenticationState(string token) private AuthenticationState BuildAuthenticationState(string token)
{ {
httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token); httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(ParseClaimsFromJwt(token), "jwt"))); return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(ParseClaimsFromJwt(token), "jwt")));
} }
public async Task<TokenData> GetTokenData() public async Task<TokenData> GetTokenData()
{ {
var token = await js.GetFromLocalStorage(TOKENKEY); var authState = await GetAuthenticationStateAsync();
//TokenData result = JsonSerializer.Deserialize<TokenData>(token); var user = authState.User;
//return result;
TokenData? result = JsonSerializer.Deserialize<TokenData>(token);
if (result == null) if (user.Identity is null || !user.Identity.IsAuthenticated)
throw new InvalidOperationException("Usuario no autenticado.");
var tokenString = await js.GetFromLocalStorage(TOKENKEY); // <-- ACA RECUPERAMOS EL JWT
return new TokenData
{ {
// Maneja el caso en el que la deserialización falla y devuelve null userName = user.Identity.Name ?? string.Empty,
// Puedes lanzar una excepción, retornar un valor predeterminado, o manejar el error de otra forma role = user.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Role)?.Value ?? string.Empty,
throw new InvalidOperationException("El token no se pudo deserializar en un objeto TokenData."); token = tokenString ?? string.Empty, // <-- ACA SETEAMOS el token string
expiryTimeStamp = DateTime.UtcNow
};
} }
//public async Task<TokenData> GetTokenData()
//{
// var authState = await GetAuthenticationStateAsync();
// var user = authState.User;
// if (user.Identity is null || !user.Identity.IsAuthenticated)
// throw new InvalidOperationException("Usuario no autenticado.");
// return new TokenData
// {
// userName = user.Identity.Name ?? string.Empty,
// role = user.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Role)?.Value ?? string.Empty,
// expiryTimeStamp = DateTime.UtcNow // Opcional: ajustar si extraes exp claim
// };
//}
return result;
}
public async Task Login(string token) public async Task Login(string token)
{ {
await js.RemoveItem(TOKENKEY); await js.RemoveItem(TOKENKEY);
@ -55,39 +80,14 @@ namespace phronCare.UIBlazor.Services.Authorization
var authState = BuildAuthenticationState(token); var authState = BuildAuthenticationState(token);
NotifyAuthenticationStateChanged(Task.FromResult(authState)); NotifyAuthenticationStateChanged(Task.FromResult(authState));
} }
public async Task Logout() public async Task Logout()
{ {
httpClient.DefaultRequestHeaders.Authorization = null; httpClient.DefaultRequestHeaders.Authorization = null;
await js.RemoveItem(TOKENKEY); await js.RemoveItem(TOKENKEY);
NotifyAuthenticationStateChanged(Task.FromResult(Anonimo)); NotifyAuthenticationStateChanged(Task.FromResult(Anonimo));
} }
//private IEnumerable<Claim> ParseClaimsFromJwt(string jwt)
//{
// var claims = new List<Claim>();
// var payload = jwt.Split('.')[1];
// var jsonBytes = ParseBase64WithoutPadding(payload);
// var keyValuePairs = JsonSerializer.Deserialize<Dictionary<string, object>>(jsonBytes);
// keyValuePairs.TryGetValue(ClaimTypes.Role, out object roles);
// if (roles != null)
// {
// if (roles.ToString().Trim().StartsWith("["))
// {
// var parsedRoles = JsonSerializer.Deserialize<string[]>(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<Claim> ParseClaimsFromJwt(string jwt) private IEnumerable<Claim> ParseClaimsFromJwt(string jwt)
{ {
var claims = new List<Claim>(); var claims = new List<Claim>();
@ -97,8 +97,7 @@ namespace phronCare.UIBlazor.Services.Authorization
if (keyValuePairs != null && keyValuePairs.TryGetValue(ClaimTypes.Role, out object roles)) if (keyValuePairs != null && keyValuePairs.TryGetValue(ClaimTypes.Role, out object roles))
{ {
// Verificamos si roles no es null y lo convertimos a string de manera segura var rolesString = roles?.ToString() ?? string.Empty;
string rolesString = roles?.ToString() ?? string.Empty; // Aquí usamos un valor por defecto si es null
if (!string.IsNullOrEmpty(rolesString)) if (!string.IsNullOrEmpty(rolesString))
{ {
@ -126,6 +125,7 @@ namespace phronCare.UIBlazor.Services.Authorization
return claims; return claims;
} }
private byte[] ParseBase64WithoutPadding(string base64) private byte[] ParseBase64WithoutPadding(string base64)
{ {
switch (base64.Length % 4) switch (base64.Length % 4)
@ -135,11 +135,17 @@ namespace phronCare.UIBlazor.Services.Authorization
} }
return Convert.FromBase64String(base64); return Convert.FromBase64String(base64);
} }
private bool IsJwtFormat(string token)
{
return token?.Count(c => c == '.') == 2;
}
public class TokenData public class TokenData
{ {
public string userName { get; set; } = string.Empty; public string userName { get; set; } = string.Empty;
public string token { get; set; } = string.Empty;
public string role { get; set; } = string.Empty; public string role { get; set; } = string.Empty;
public string token { get; set; } = string.Empty;
public DateTime expiryTimeStamp { get; set; } public DateTime expiryTimeStamp { get; set; }
} }
} }