146 lines
6.0 KiB
C#
146 lines
6.0 KiB
C#
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<AuthenticationState> 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<TokenData> GetTokenData()
|
|
{
|
|
var token = await js.GetFromLocalStorage(TOKENKEY);
|
|
//TokenData result = JsonSerializer.Deserialize<TokenData>(token);
|
|
//return result;
|
|
TokenData? result = JsonSerializer.Deserialize<TokenData>(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<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)
|
|
{
|
|
var claims = new List<Claim>();
|
|
var payload = jwt.Split('.')[1];
|
|
var jsonBytes = ParseBase64WithoutPadding(payload);
|
|
var keyValuePairs = JsonSerializer.Deserialize<Dictionary<string, object>>(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<string[]>(rolesString) ?? Array.Empty<string>();
|
|
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; }
|
|
}
|
|
}
|
|
} |