LibraryManagement / BlazorWebAssembly /Providers /JwtAuthenticationStateProvider.cs
Yuyuqt
add: authorized pages, firebase
d8a7fc4
Raw
History Blame Contribute Delete
3.91 kB
using System.Net.Http.Headers;
using System.Security.Claims;
using System.Text.Json;
using Blazored.LocalStorage;
using Microsoft.AspNetCore.Components.Authorization;
namespace BlazorWebAssembly.Providers
{
public class JwtAuthenticationStateProvider : AuthenticationStateProvider
{
private readonly ILocalStorageService _localStorage;
private readonly HttpClient _httpClient;
private readonly AuthenticationState _anonymous;
public JwtAuthenticationStateProvider(ILocalStorageService localStorage, HttpClient httpClient)
{
_localStorage = localStorage;
_httpClient = httpClient;
_anonymous = new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity()));
}
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
{
var token = await _localStorage.GetItemAsync<string>("authToken");
if (string.IsNullOrWhiteSpace(token))
return _anonymous;
var claims = ParseClaimsFromJwt(token);
// Check expiration
var expClaim = claims.FirstOrDefault(c => c.Type == "exp");
if (expClaim != null && long.TryParse(expClaim.Value, out long expTime))
{
var expDateTime = DateTimeOffset.FromUnixTimeSeconds(expTime).UtcDateTime;
if (expDateTime <= DateTime.UtcNow)
{
await _localStorage.RemoveItemAsync("authToken");
return _anonymous;
}
}
_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer", token);
return new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(claims, "jwt")));
}
public void NotifyUserAuthentication(string token)
{
var authenticatedUser = new ClaimsPrincipal(new ClaimsIdentity(ParseClaimsFromJwt(token), "jwt"));
var authState = Task.FromResult(new AuthenticationState(authenticatedUser));
NotifyAuthenticationStateChanged(authState);
}
public void NotifyUserLogout()
{
var authState = Task.FromResult(_anonymous);
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)
{
foreach (var kvp in keyValuePairs)
{
string claimType = kvp.Key;
if (claimType == "role" || claimType == "Role") claimType = ClaimTypes.Role;
else if (claimType == "unique_name" || claimType == "name") claimType = ClaimTypes.Name;
if (kvp.Value is JsonElement element && element.ValueKind == JsonValueKind.Array)
{
foreach (var item in element.EnumerateArray())
{
claims.Add(new Claim(claimType, item.ToString()));
}
}
else
{
claims.Add(new Claim(claimType, kvp.Value.ToString() ?? ""));
}
}
}
return claims;
}
private byte[] ParseBase64WithoutPadding(string base64)
{
switch (base64.Length % 4)
{
case 2: base64 += "=="; break;
case 3: base64 += "="; break;
}
return Convert.FromBase64String(base64);
}
}
}