82 lines
2.6 KiB
C#
82 lines
2.6 KiB
C#
using System.Security.Claims;
|
|
using System.Text.Json;
|
|
using Microsoft.AspNetCore.Components.Authorization;
|
|
using NexusReader.Application.Abstractions.Services;
|
|
|
|
namespace NexusReader.UI.Shared.Services;
|
|
|
|
public class NexusAuthenticationStateProvider : AuthenticationStateProvider
|
|
{
|
|
private readonly INativeStorageService _storageService;
|
|
private const string TokenKey = "nexus_auth_token";
|
|
|
|
public NexusAuthenticationStateProvider(INativeStorageService storageService)
|
|
{
|
|
_storageService = storageService;
|
|
}
|
|
|
|
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
|
|
{
|
|
try
|
|
{
|
|
var result = await _storageService.GetSecureString(TokenKey);
|
|
var token = result.IsSuccess ? result.Value : null;
|
|
|
|
if (string.IsNullOrWhiteSpace(token))
|
|
{
|
|
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
|
|
}
|
|
|
|
var identity = new ClaimsIdentity(ParseClaimsFromJwt(token), "jwt");
|
|
var user = new ClaimsPrincipal(identity);
|
|
|
|
return new AuthenticationState(user);
|
|
}
|
|
catch (Exception)
|
|
{
|
|
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
|
|
}
|
|
}
|
|
|
|
public void NotifyUserAuthentication(string token)
|
|
{
|
|
var identity = new ClaimsIdentity(ParseClaimsFromJwt(token), "jwt");
|
|
var user = new ClaimsPrincipal(identity);
|
|
var authState = Task.FromResult(new AuthenticationState(user));
|
|
NotifyAuthenticationStateChanged(authState);
|
|
}
|
|
|
|
public void NotifyUserLogout()
|
|
{
|
|
var guest = new ClaimsPrincipal(new ClaimsIdentity());
|
|
var authState = Task.FromResult(new AuthenticationState(guest));
|
|
NotifyAuthenticationStateChanged(authState);
|
|
}
|
|
|
|
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)
|
|
{
|
|
claims.AddRange(keyValuePairs.Select(kvp => new Claim(kvp.Key, kvp.Value.ToString() ?? string.Empty)));
|
|
}
|
|
|
|
return claims;
|
|
}
|
|
|
|
private byte[] ParseBase64WithoutPadding(string base64)
|
|
{
|
|
switch (base64.Length % 4)
|
|
{
|
|
case 2: base64 += "=="; break;
|
|
case 3: base64 += "="; break;
|
|
}
|
|
return Convert.FromBase64String(base64);
|
|
}
|
|
}
|