Files
monorepo/LCU.API.Internal.OnlineLoanApp/OnlineBankingAuth/Tokens/TokenService.cs
T
2026-03-11 11:18:25 -05:00

169 lines
5.8 KiB
C#

using System.Globalization;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Authentication;
using System.Security.Claims;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using Newtonsoft.Json;
using Landmark.OLA.Application.Common.Security;
using Landmark.OLA.Models.Core;
using Landmark.OLA.Models.OnlineBanking;
using OnlineBankingAuth.Configuration;
namespace OnlineBankingAuth.Tokens
{
public class TokenService : ITokenService
{
private readonly SecuritySettings _settings;
public TokenService(
IOptions<SecuritySettings> settings)
{
_settings = settings.Value;
}
public string CreateOnlineBankingJWT(OnlineBankingToken payload)
{
var handler = new JwtSecurityTokenHandler { MapInboundClaims = false };
var claims = new List<Claim>
{
new(Constants.MemberID, payload.MemberID ?? string.Empty),
new(Constants.IndividualID, payload.IndividualID ?? string.Empty),
new(Constants.FI_ID, payload.FI_ID ?? string.Empty),
new(Constants.InProgressLoanId, payload.LoanId ?? string.Empty),
new(Constants.IsTwoFactor, payload.IsTwoFactor.ToString())
};
var jwt = new JwtSecurityToken(
claims: claims,
expires: DateTime.UtcNow.AddMinutes(15)
);
var token = handler.WriteToken(jwt);
var encrypted = CookieCryptor.EncryptJwt(token, _settings.TokenSecret);
return Constants.TokenPrefix + encrypted;
}
public string RenewOnlineBankingJWT(HttpContext context)
{
var cookies = context.Request.Cookies;
string cookieValue = null;
if (cookies[Constants.TokenPayload] != null)
{
var jwtCookie = cookies[Constants.TokenPayload][Constants.TokenPrefix.Length..];
var jwt = CookieCryptor.DecryptJwt(jwtCookie, _settings.TokenSecret);
if (!IsTokenReadable(jwt))
{
throw new AuthenticationException("Could not parse token.");
}
var prevToken = ReadJwtSecurityToken(jwt);
cookieValue = Constants.TokenPrefix + GenerateEncodedToken(prevToken);
}
return cookieValue;
}
public string RenewAuthorization(HttpContext context)
{
var cookies = context.Request.Cookies;
string cookieValue = null;
if (cookies[Constants.TokenAuthorization] != null)
{
cookieValue = cookies[Constants.TokenAuthorization];
}
return cookieValue;
}
public OnlineBankingToken GetAuthenticatedDataFromCookie(HttpContext context)
{
var cookies = context.Request.Cookies;
if (!string.IsNullOrEmpty(cookies[Constants.TokenPayload]))
{
return GetAuthenticatedUserDataFromJwt(cookies[Constants.TokenPayload][Constants.TokenPrefix.Length..]);
}
return null;
}
private string GenerateEncodedToken(JwtSecurityToken jwtToken)
{
var tokenHandler = new JwtSecurityTokenHandler { };
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(jwtToken.Claims),
Expires = DateTime.UtcNow.AddMinutes(15)
};
var token = tokenHandler.CreateEncodedJwt(tokenDescriptor);
var encryptedToken = CookieCryptor.EncryptJwt(token, _settings.TokenSecret);
return encryptedToken;
}
private static bool TryGet(JwtSecurityToken jwt, string key, out string? value)
{
var claim = jwt.Claims.FirstOrDefault(c => c.Type == key)
?? jwt.Claims.FirstOrDefault(c => string.Equals(c.Type, key, StringComparison.OrdinalIgnoreCase));
if (claim is not null) { value = claim.Value; return true; }
foreach (var kv in jwt.Payload)
if (string.Equals(kv.Key, key, StringComparison.OrdinalIgnoreCase))
{
value = Convert.ToString(kv.Value, CultureInfo.InvariantCulture);
return true;
}
value = null;
return false;
}
public OnlineBankingToken GetAuthenticatedUserDataFromJwt(string encryptedJwt)
{
var jwt = CookieCryptor.DecryptJwt(encryptedJwt, _settings.TokenSecret);
var token = ReadJwtSecurityToken(jwt);
var data = new OnlineBankingToken();
if (!TryGet(token, Constants.MemberID, out var memberId)) return null;
if (!TryGet(token, Constants.FI_ID, out var fiId)) return null;
data.MemberID = memberId!;
data.FI_ID = fiId!;
if (TryGet(token, Constants.IsTwoFactor, out var twoFa))
data.IsTwoFactor = bool.TryParse(twoFa, out var b) && b;
if (TryGet(token, Constants.IndividualID, out var indId))
data.IndividualID = indId;
return data;
}
private static JwtSecurityToken ReadJwtSecurityToken(string jwt)
{
return new JwtSecurityTokenHandler().ReadJwtToken(jwt);
}
private static bool IsTokenReadable(string jwt)
{
return new JwtSecurityTokenHandler().CanReadToken(jwt);
}
public string CreateAuthMetaToken(MemberMeta meta)
{
var json = JsonConvert.SerializeObject(meta);
var plainTextBytes = System.Text.Encoding.UTF8.GetBytes(json);
return Convert.ToBase64String(plainTextBytes);
}
}
}