Spaces:
Sleeping
Sleeping
File size: 3,911 Bytes
6f32ae8 d8a7fc4 6f32ae8 d8a7fc4 6f32ae8 d8a7fc4 6f32ae8 d8a7fc4 6f32ae8 d8a7fc4 6f32ae8 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 | 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);
}
}
}
|