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");
}
}
}