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 settings) { _settings = settings.Value; } public string CreateOnlineBankingJWT(OnlineBankingToken payload) { var handler = new JwtSecurityTokenHandler { MapInboundClaims = false }; var claims = new List { 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); } } }