using Biskilog_Accounting.Shared.ClientContractModels; using Biskilog_Accounting.Shared.Enums; using Biskilog_Accounting.Shared.Interfaces; using Blazored.LocalStorage; using Blazored.SessionStorage; using Microsoft.Extensions.Configuration; using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Text; namespace Biskilog_Accounting.ServiceRepo { public class TokenService : ITokenService { private IConfiguration m_configuration { get; } private readonly ISessionStorageService m_sessionStorage; private readonly ILocalStorageService m_localStorage; public TokenService(IConfiguration a_configuration, ISessionStorageService a_sessionStorage = null, ILocalStorageService a_localStorage = null) { m_configuration = a_configuration; m_sessionStorage = a_sessionStorage; m_localStorage = a_localStorage; } /// /// Validates a user access token /// /// AuthEnums.Valid if token is a valid and unexpired token public AuthEnums ValidateToken(string a_token) { try { string token = a_token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); JwtSecurityToken jwtToken = (JwtSecurityToken)handler.ReadToken(token); if (jwtToken.ValidFrom <= DateTime.Now && jwtToken.ValidTo > DateTime.Now) return AuthEnums.Valid; return AuthEnums.Expired; } catch (Exception ex) { return AuthEnums.Invalid; } } /// /// Generates an access token based on the user /// /// A tokenized string public string GenerateToken(Userauth a_user, Contract a_clientContract, Databasemap a_database, List a_business, bool a_comparison) { try { //create claims details based on the user information var claims = new[] { new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), new Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToString()), new Claim("ContractStart",a_clientContract.StartDate !.Value.ToString()), new Claim("ContractEnd",a_clientContract.EndDate!.Value.ToString()), new Claim("UserId", a_user.UserId.ToString()), new Claim("Username", a_user.Username.ToString()), new Claim("DbId",a_database.DbNo.ToString()), new Claim("ComparisonMode",a_comparison.ToString()), new Claim("BranchId",a_business[0].ToString()), new Claim("BranchAccess",string.Join(", ", a_business.ToArray())), new Claim("ClientId", a_user.ClientId.ToString()), }; var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(m_configuration["Jwt:Key"]!)); var signIn = new SigningCredentials(key, SecurityAlgorithms.HmacSha256); var token = new JwtSecurityToken(m_configuration["Jwt:Issuer"], m_configuration["Jwt:Audience"], claims, expires: DateTime.UtcNow.AddDays(14), signingCredentials: signIn); return $"{new JwtSecurityTokenHandler().WriteToken(token)}"; } catch (Exception ex) { Console.WriteLine(ex.Message); return AuthEnums.Error.ToString(); } } /// ///Deserializes the token string if valid to return the specified user role id in the token string /// /// /// RoleId public int? GetDatabaseIdFromToken(string a_token) { if (ValidateToken(a_token) == AuthEnums.Valid) { string token = a_token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); JwtSecurityToken jwtToken = (JwtSecurityToken)handler.ReadToken(token); return int.Parse(jwtToken.Claims.First(claim => claim.Type == "DbId").Value); } return null; } /// ///Deserializes the token string if valid to return the specified user id in the token string /// /// /// UserId public int? GetUserIdFromToken(string a_token) { if (ValidateToken(a_token) == AuthEnums.Valid) { string token = a_token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); JwtSecurityToken jwtToken = (JwtSecurityToken)handler.ReadToken(token); return int.Parse(jwtToken.Claims.First(claim => claim.Type == "UserId").Value); } return null; } /// ///Deserializes the token string if valid to return the specified username in the token string /// /// /// Username public string? GetUserNameFromToken(string a_token) { if (ValidateToken(a_token) == AuthEnums.Valid) { string token = a_token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); JwtSecurityToken jwtToken = (JwtSecurityToken)handler.ReadToken(token); return jwtToken.Claims.First(claim => claim.Type == "Username").Value; } return null; } /// ///Deserializes the token string if valid to return the specified branchId in the token string /// /// /// Username public string? GetBaseBranch(string a_token) { if (ValidateToken(a_token) == AuthEnums.Valid) { string token = a_token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); JwtSecurityToken jwtToken = (JwtSecurityToken)handler.ReadToken(token); return jwtToken.Claims.First(claim => claim.Type == "BranchId").Value; } return null; } public bool? GetComparison(string a_token) { if (ValidateToken(a_token) == AuthEnums.Valid) { string token = a_token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); JwtSecurityToken jwtToken = (JwtSecurityToken)handler.ReadToken(token); return bool.Parse(jwtToken.Claims.First(claim => claim.Type == "ComparisonMode").Value); } return null; } /// ///Deserializes the token string if valid to return the specified list of branches a user has access to in the token string /// /// /// Username public string? GetAllBranch(string a_token) { if (ValidateToken(a_token) == AuthEnums.Valid) { string token = a_token.Substring(6).Trim(); var handler = new JwtSecurityTokenHandler(); JwtSecurityToken jwtToken = (JwtSecurityToken)handler.ReadToken(token); return jwtToken.Claims.First(claim => claim.Type == "BranchAccess").Value; } return null; } /// /// Return a specified list of branches a user has access if comparison mode is set otherwise returns only the /// active branch on the list /// /// /// public IEnumerable BranchIds(string a_token) { List branchIds = new List(); if (ValidateToken(a_token) == AuthEnums.Valid) { bool comparison = GetComparison(a_token)!.Value; if (comparison) { string? branches = GetAllBranch(a_token); if (branches != null) { string[] branchArray = branches!.Split(); branchIds.AddRange(branchArray); } } else { string? baseBranch = GetBaseBranch(a_token); branchIds.Add(baseBranch!); } } return branchIds.AsEnumerable(); } public async Task SetToken(string a_token, bool a_remember) { if (a_remember) { await m_localStorage.SetItemAsStringAsync("token", $"Bearer {a_token}"); } else { await m_sessionStorage.SetItemAsStringAsync("token", $"Bearer {a_token}"); } } public async Task GetToken() { string token = await m_localStorage.GetItemAsStringAsync("token"); if (String.IsNullOrEmpty(token)) { token = await m_sessionStorage.GetItemAsStringAsync("token"); } return token; } public async Task ClearToken() { await m_localStorage.ClearAsync(); await m_sessionStorage.ClearAsync(); } public async Task IsTokenSet() { return await m_localStorage.ContainKeyAsync("token") || await m_sessionStorage.ContainKeyAsync("token"); } } }