141 lines
5.9 KiB
C#
141 lines
5.9 KiB
C#
using Blazored.LocalStorage;
|
|
using Atomx.Common.Configuration;
|
|
using Atomx.Common.Utils;
|
|
using Atomx.Utils.Extension;
|
|
using Microsoft.AspNetCore.Components;
|
|
using Microsoft.AspNetCore.Components.Authorization;
|
|
using System.IdentityModel.Tokens.Jwt;
|
|
using System.Security.Claims;
|
|
|
|
namespace Atomx.Admin.Client.Utils
|
|
{
|
|
public class PersistentAuthenticationStateProvider : AuthenticationStateProvider
|
|
{
|
|
readonly ClaimsPrincipal anonymous = new(new ClaimsIdentity());
|
|
|
|
static readonly Task<AuthenticationState> defaultUnauthenticatedTask = Task.FromResult(new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity())));
|
|
readonly Task<AuthenticationState> authenticationStateTask = defaultUnauthenticatedTask;
|
|
|
|
readonly ILocalStorageService _localStorage;
|
|
|
|
public PersistentAuthenticationStateProvider(PersistentComponentState state, ILocalStorageService localStorageService)
|
|
{
|
|
_localStorage = localStorageService;
|
|
|
|
if (!state.TryTakeFromJson<UserInfo>(nameof(UserInfo), out var userInfo) || userInfo is null)
|
|
{
|
|
return;
|
|
}
|
|
|
|
var claims = new List<Claim>
|
|
{
|
|
new(ClaimKeys.Id, userInfo.Id.ToString()),
|
|
new(ClaimKeys.Name, userInfo.Name),
|
|
new(ClaimKeys.Email, userInfo.Email),
|
|
new(ClaimKeys.Mobile, userInfo.MobilePhone),
|
|
new(ClaimKeys.Role, userInfo.Role),
|
|
};
|
|
foreach (var role in userInfo.Permissions)
|
|
{
|
|
claims.Add(new Claim(ClaimKeys.Permission, role));
|
|
}
|
|
|
|
authenticationStateTask = Task.FromResult(
|
|
new AuthenticationState(new ClaimsPrincipal(new ClaimsIdentity(claims, authenticationType: nameof(PersistentAuthenticationStateProvider)))));
|
|
}
|
|
|
|
public override async Task<AuthenticationState> GetAuthenticationStateAsync()
|
|
{
|
|
try
|
|
{
|
|
var jwtToken = await _localStorage.GetItemAsStringAsync(StorageKeys.JWTTokenKeyName);
|
|
if (string.IsNullOrEmpty(jwtToken))
|
|
return await Task.FromResult(new AuthenticationState(anonymous));
|
|
else
|
|
{
|
|
var getUserClaims = DecryptToken(jwtToken);
|
|
if (getUserClaims == null)
|
|
return await Task.FromResult(new AuthenticationState(anonymous));
|
|
else
|
|
{
|
|
var claimsPrincipal = SetClaimPrincipal(getUserClaims);
|
|
return await Task.FromResult(new AuthenticationState(claimsPrincipal));
|
|
}
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
return await Task.FromResult(new AuthenticationState(anonymous));
|
|
}
|
|
}
|
|
|
|
public ClaimsPrincipal SetClaimPrincipal(UserInfo customUserClaims)
|
|
{
|
|
if (string.IsNullOrEmpty(customUserClaims.Name))
|
|
return new ClaimsPrincipal();
|
|
else
|
|
{
|
|
var claims = new List<Claim>
|
|
{
|
|
new(ClaimKeys.Id, customUserClaims.Id.ToString()),
|
|
new(ClaimKeys.Name, customUserClaims.Name),
|
|
new(ClaimKeys.Email, customUserClaims.Email),
|
|
new(ClaimKeys.Mobile, customUserClaims.MobilePhone),
|
|
new(ClaimKeys.Role, customUserClaims.Role.ToString()),
|
|
};
|
|
foreach (var role in customUserClaims.Permissions)
|
|
{
|
|
claims.Add(new Claim(ClaimKeys.Permission, role));
|
|
}
|
|
return new ClaimsPrincipal(new ClaimsIdentity(claims, authenticationType: nameof(PersistentAuthenticationStateProvider)));
|
|
}
|
|
|
|
}
|
|
|
|
public void UpdateAuthenticationState(string jwtToken = "")
|
|
{
|
|
var claimsPrincipal = new ClaimsPrincipal();
|
|
if (!string.IsNullOrEmpty(jwtToken))
|
|
{
|
|
var getUserClaims = DecryptToken(jwtToken);
|
|
claimsPrincipal = SetClaimPrincipal(getUserClaims);
|
|
}
|
|
|
|
NotifyAuthenticationStateChanged(Task.FromResult(new AuthenticationState(claimsPrincipal)));
|
|
}
|
|
|
|
private UserInfo DecryptToken(string jwtToken)
|
|
{
|
|
if (string.IsNullOrEmpty(jwtToken))
|
|
return new UserInfo();
|
|
else
|
|
{
|
|
var handler = new JwtSecurityTokenHandler();
|
|
var token = handler.ReadJwtToken(jwtToken);
|
|
|
|
|
|
|
|
var id = token.Claims.SingleOrDefault(x => x.Type == ClaimKeys.Id)?.Value ?? string.Empty;
|
|
var name = token.Claims.SingleOrDefault(x => x.Type == ClaimKeys.Name)?.Value ?? string.Empty;
|
|
var email = token.Claims.SingleOrDefault(x => x.Type == ClaimKeys.Email)?.Value ?? string.Empty;
|
|
var phone = token.Claims.SingleOrDefault(x => x.Type == ClaimKeys.Mobile)?.Value ?? string.Empty;
|
|
var role = token.Claims.SingleOrDefault(x => x.Type == ClaimKeys.Role)?.Value ?? string.Empty;
|
|
var permissions = token.Claims.Where(x => x.Type == ClaimKeys.Permission).Select(s => s.Value).ToArray();
|
|
|
|
return new UserInfo(id.ToLong(), name, email, phone, role, permissions);
|
|
}
|
|
}
|
|
|
|
public async Task MarkUserAsLoggedOut()
|
|
{
|
|
await _localStorage.RemoveItemAsync(StorageKeys.JWTTokenKeyName);
|
|
await _localStorage.RemoveItemAsync(StorageKeys.RefreshTokenKeyName);
|
|
|
|
var authState = Task.FromResult(new AuthenticationState(anonymous));
|
|
|
|
NotifyAuthenticationStateChanged(authState);
|
|
}
|
|
}
|
|
|
|
public record UserInfo(long Id = 0, string Name = null!, string Email = null!, string MobilePhone = null!, string Role = null!, string[] Permissions = null!);
|
|
} |