MRB webassembly
This commit is contained in:
232
MesaFabApproval.Client/Services/AuthenticationService.cs
Normal file
232
MesaFabApproval.Client/Services/AuthenticationService.cs
Normal file
@ -0,0 +1,232 @@
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Security.Claims;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
using System.Text.Json;
|
||||
|
||||
using MesaFabApproval.Shared.Models;
|
||||
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
namespace MesaFabApproval.Client.Services;
|
||||
|
||||
public interface IAuthenticationService {
|
||||
Task<ClaimsPrincipal> SendAuthenticationRequest(string loginId, string password);
|
||||
Task<ClaimsPrincipal> AttemptLocalUserAuth();
|
||||
Task<ClaimsPrincipal> FetchAuthState();
|
||||
Task ClearTokens();
|
||||
Task ClearCurrentUser();
|
||||
Task SetTokens(string jwt, string refreshToken);
|
||||
Task SetLoginId(string loginId);
|
||||
Task SetCurrentUser(User user);
|
||||
Task<User> GetCurrentUser();
|
||||
Task<AuthTokens> GetAuthTokens();
|
||||
Task<string> GetLoginId();
|
||||
ClaimsPrincipal GetClaimsPrincipalFromJwt(string jwt);
|
||||
}
|
||||
|
||||
public class AuthenticationService : IAuthenticationService {
|
||||
private readonly ILocalStorageService _localStorageService;
|
||||
private readonly IMemoryCache _cache;
|
||||
private readonly IHttpClientFactory _httpClientFactory;
|
||||
|
||||
public AuthenticationService(ILocalStorageService localStorageService,
|
||||
IMemoryCache cache,
|
||||
IHttpClientFactory httpClientFactory) {
|
||||
_localStorageService = localStorageService ??
|
||||
throw new ArgumentNullException("ILocalStorageService not injected");
|
||||
_cache = cache ?? throw new ArgumentNullException("IMemoryCache not injected");
|
||||
_httpClientFactory = httpClientFactory ?? throw new ArgumentNullException("IHttpClientFactory not injected");
|
||||
}
|
||||
|
||||
public async Task<ClaimsPrincipal> SendAuthenticationRequest(string loginId, string password) {
|
||||
if (string.IsNullOrWhiteSpace(loginId)) throw new ArgumentException("loginId cannot be null or empty");
|
||||
if (string.IsNullOrWhiteSpace(password)) throw new ArgumentException("password cannot be null or empty");
|
||||
|
||||
HttpClient httpClient = _httpClientFactory.CreateClient("API");
|
||||
|
||||
AuthAttempt authAttempt = new() {
|
||||
LoginID = loginId,
|
||||
Password = password
|
||||
};
|
||||
|
||||
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "auth/login");
|
||||
|
||||
request.Content = new StringContent(JsonSerializer.Serialize(authAttempt),
|
||||
Encoding.UTF8,
|
||||
"application/json");
|
||||
|
||||
HttpResponseMessage httpResponseMessage = await httpClient.SendAsync(request);
|
||||
|
||||
if (httpResponseMessage.IsSuccessStatusCode) {
|
||||
string responseContent = await httpResponseMessage.Content.ReadAsStringAsync();
|
||||
|
||||
JsonSerializerOptions jsonSerializerOptions = new() {
|
||||
PropertyNameCaseInsensitive = true
|
||||
};
|
||||
|
||||
LoginResult loginResult = JsonSerializer.Deserialize<LoginResult>(responseContent, jsonSerializerOptions) ??
|
||||
throw new Exception("Unable to parse login result from API response");
|
||||
|
||||
if (!loginResult.IsAuthenticated) throw new Exception($"User with Login ID {loginId} not authorized");
|
||||
|
||||
await SetLoginId(loginId);
|
||||
|
||||
await SetTokens(loginResult.AuthTokens.JwtToken, loginResult.AuthTokens.RefreshToken);
|
||||
|
||||
await SetCurrentUser(loginResult.User);
|
||||
|
||||
ClaimsPrincipal principal = GetClaimsPrincipalFromJwt(loginResult.AuthTokens.JwtToken);
|
||||
|
||||
return principal;
|
||||
} else {
|
||||
throw new Exception($"Login API request failed for {loginId}, because {httpResponseMessage.ReasonPhrase}");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ClaimsPrincipal> AttemptLocalUserAuth() {
|
||||
WindowsIdentity? user = WindowsIdentity.GetCurrent();
|
||||
|
||||
if (user is null)
|
||||
throw new Exception("no authenticated user found");
|
||||
|
||||
if (!user.IsAuthenticated)
|
||||
throw new Exception("you are not authenticated");
|
||||
|
||||
HttpClient httpClient = _httpClientFactory.CreateClient("API");
|
||||
|
||||
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, "auth/login/localWindows");
|
||||
|
||||
request.Content = new StringContent(JsonSerializer.Serialize(user),
|
||||
Encoding.UTF8,
|
||||
"application/json");
|
||||
|
||||
HttpResponseMessage httpResponseMessage = await httpClient.SendAsync(request);
|
||||
|
||||
if (httpResponseMessage.IsSuccessStatusCode) {
|
||||
string responseContent = await httpResponseMessage.Content.ReadAsStringAsync();
|
||||
|
||||
JsonSerializerOptions jsonSerializerOptions = new() {
|
||||
PropertyNameCaseInsensitive = true
|
||||
};
|
||||
|
||||
LoginResult loginResult = JsonSerializer.Deserialize<LoginResult>(responseContent, jsonSerializerOptions) ??
|
||||
throw new Exception("Unable to parse login result from API response");
|
||||
|
||||
if (!loginResult.IsAuthenticated) throw new Exception($"User with Login ID {user.Name} not authorized");
|
||||
|
||||
await SetLoginId(loginResult.User.LoginID);
|
||||
|
||||
await SetTokens(loginResult.AuthTokens.JwtToken, loginResult.AuthTokens.RefreshToken);
|
||||
|
||||
await SetCurrentUser(loginResult.User);
|
||||
|
||||
ClaimsPrincipal principal = GetClaimsPrincipalFromJwt(loginResult.AuthTokens.JwtToken);
|
||||
|
||||
return principal;
|
||||
} else {
|
||||
throw new Exception($"Login API request failed for {user.Name}, because {httpResponseMessage.ReasonPhrase}");
|
||||
}
|
||||
}
|
||||
|
||||
public async Task<ClaimsPrincipal> FetchAuthState() {
|
||||
string? jwt = _cache.Get<string>("MesaFabApprovalJwt");
|
||||
|
||||
if (jwt is null) jwt = await _localStorageService.GetItem("MesaFabApprovalJwt");
|
||||
|
||||
if (jwt is null) throw new Exception("Unable to find JWT");
|
||||
|
||||
ClaimsPrincipal principal = GetClaimsPrincipalFromJwt(jwt);
|
||||
|
||||
return principal;
|
||||
}
|
||||
|
||||
public async Task ClearTokens() {
|
||||
_cache.Remove("MesaFabApprovalJwt");
|
||||
await _localStorageService.RemoveItem("MesaFabApprovalJwt");
|
||||
_cache.Remove("MesaFabApprovalRefreshToken");
|
||||
await _localStorageService.RemoveItem("MesaFabApprovalRefreshToken");
|
||||
}
|
||||
|
||||
public async Task SetTokens(string jwt, string refreshToken) {
|
||||
if (string.IsNullOrWhiteSpace(jwt)) throw new ArgumentNullException("JWT cannot be null or empty");
|
||||
if (string.IsNullOrWhiteSpace(refreshToken)) throw new ArgumentNullException("Refresh token cannot be null or empty");
|
||||
|
||||
_cache.Set<string>("MesaFabApprovalJwt", jwt);
|
||||
await _localStorageService.AddItem("MesaFabApprovalJwt", jwt);
|
||||
_cache.Set<string>("MesaFabApprovalRefreshToken", refreshToken);
|
||||
await _localStorageService.AddItem("MesaFabApprovalRefreshToken", refreshToken);
|
||||
}
|
||||
|
||||
public async Task SetLoginId(string loginId) {
|
||||
if (string.IsNullOrWhiteSpace(loginId)) throw new ArgumentNullException("LoginId cannot be null or empty");
|
||||
|
||||
_cache.Set<string>("MesaFabApprovalUserId", loginId);
|
||||
await _localStorageService.AddItem("MesaFabApprovalUserId", loginId);
|
||||
}
|
||||
|
||||
public async Task SetCurrentUser(User user) {
|
||||
if (user is null) throw new ArgumentNullException("User cannot be null");
|
||||
|
||||
_cache.Set<User>("MesaFabApprovalCurrentUser", user);
|
||||
await _localStorageService.AddItem<User>("MesaFabApprovalCurrentUser", user);
|
||||
}
|
||||
|
||||
public async Task ClearCurrentUser() {
|
||||
_cache.Remove("MesaFabApprovalCurrentUser");
|
||||
await _localStorageService.RemoveItem("MesaFabApprovalCurrentUser");
|
||||
_cache.Remove("MesaFabApprovalUserId");
|
||||
await _localStorageService.RemoveItem("MesaFabApprovalUserId");
|
||||
}
|
||||
|
||||
public async Task<User> GetCurrentUser() {
|
||||
User? currentUser = null;
|
||||
|
||||
currentUser = _cache.Get<User>("MesaFabApprovalCurrentUser") ??
|
||||
await _localStorageService.GetItem<User>("MesaFabApprovalCurrentUser");
|
||||
|
||||
return currentUser;
|
||||
}
|
||||
|
||||
public async Task<AuthTokens> GetAuthTokens() {
|
||||
AuthTokens? authTokens = null;
|
||||
|
||||
string? jwt = _cache.Get<string>("MesaFabApprovalJwt");
|
||||
if (jwt is null) jwt = await _localStorageService.GetItem("MesaFabApprovalJwt");
|
||||
|
||||
string? refreshToken = _cache.Get<string>("MesaFabApprovalRefreshToken");
|
||||
if (refreshToken is null) refreshToken = await _localStorageService.GetItem("MesaFabApprovalRefreshToken");
|
||||
|
||||
if (!string.IsNullOrWhiteSpace(jwt) && !string.IsNullOrWhiteSpace(refreshToken)) {
|
||||
authTokens = new() {
|
||||
JwtToken = jwt,
|
||||
RefreshToken = refreshToken
|
||||
};
|
||||
}
|
||||
|
||||
return authTokens;
|
||||
}
|
||||
|
||||
public async Task<string> GetLoginId() {
|
||||
string? loginId = _cache.Get<string>("MesaFabApprovalUserId");
|
||||
if (loginId is null) loginId = await _localStorageService.GetItem("MesaFabApprovalUserId");
|
||||
|
||||
return loginId;
|
||||
}
|
||||
|
||||
public ClaimsPrincipal GetClaimsPrincipalFromJwt(string jwt) {
|
||||
if (string.IsNullOrWhiteSpace(jwt)) throw new ArgumentException("JWT cannot be null or empty");
|
||||
|
||||
JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler();
|
||||
|
||||
if (!tokenHandler.CanReadToken(jwt)) {
|
||||
throw new Exception("Unable to parse JWT from API");
|
||||
}
|
||||
|
||||
JwtSecurityToken jwtSecurityToken = tokenHandler.ReadJwtToken(jwt);
|
||||
|
||||
ClaimsIdentity identity = new ClaimsIdentity(jwtSecurityToken.Claims, "MesaFabApprovalWasm");
|
||||
|
||||
return new(identity);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user