using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Security.Cryptography; using Auth.Entities; using Microsoft.IdentityModel.Tokens; namespace Auth.Services { public class AuthJWT { public static Dictionary LoginSessions = new Dictionary(); public static RsaSecurityKey RsaPublicKey = LoadRSAKey("/certs/public_key.pem"); public static RsaSecurityKey RsaPrivateKey = LoadRSAKey("/certs/private_key.pem"); public static string TokenAudience = "mistox-llc-auth-token"; public static string TokenIssuer = "https://auth.mistox.com"; public static string TokenName = "mistox_session"; public static TokenValidationParameters TokenParameters = new TokenValidationParameters { ValidateIssuer = true, ValidateAudience = true, ValidateLifetime = true, ValidateIssuerSigningKey = true, ValidIssuer = TokenIssuer, ValidAudience = TokenAudience, IssuerSigningKey = RsaPublicKey, ClockSkew = TimeSpan.FromMinutes(1) }; public static string GenereateJWTToken(Account account, string RequestedSite, bool StayLoggedIn) { JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler(); SecurityTokenDescriptor tokenDiscriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity([ new Claim(ClaimTypes.NameIdentifier, account.ID.ToString()), new Claim(ClaimTypes.Name, account.UserName), new Claim(ClaimTypes.Email, account.Email), new Claim(ClaimTypes.Role, account.Role), new Claim(ClaimTypes.UserData, account.DataServer), new Claim(ClaimTypes.Dns, RequestedSite), new Claim(ClaimTypes.IsPersistent, StayLoggedIn.ToString()), ]), Expires = DateTime.UtcNow.AddDays(7), IssuedAt = DateTime.UtcNow, SigningCredentials = new SigningCredentials(RsaPrivateKey, SecurityAlgorithms.RsaSha256), Audience = TokenAudience, Issuer = TokenIssuer }; var token = tokenHandler.CreateToken(tokenDiscriptor); return tokenHandler.WriteToken(token); } public static Account? ValidateJWTToken(string Token) { try { JwtSecurityTokenHandler tokenHandler = new JwtSecurityTokenHandler(); ClaimsPrincipal principal = tokenHandler.ValidateToken( Token, TokenParameters, out SecurityToken validatedToken ); return new Account { ID = Convert.ToInt32(principal.FindFirstValue(ClaimTypes.NameIdentifier)), UserName = principal.FindFirstValue(ClaimTypes.Name)!, Email = principal.FindFirstValue(ClaimTypes.Email)!, Role = principal.FindFirstValue(ClaimTypes.Role)!, DataServer = principal.FindFirstValue(ClaimTypes.UserData)!, Site = principal.FindFirstValue(ClaimTypes.Dns)! }; } catch (Exception) { return null; } } public static string RenewJWTToken(ClaimsPrincipal principal) { return GenereateJWTToken(new Account { ID = Convert.ToInt32(principal.FindFirstValue(ClaimTypes.NameIdentifier)), UserName = principal.FindFirstValue(ClaimTypes.Name)!, Email = principal.FindFirstValue(ClaimTypes.Email)!, Role = principal.FindFirstValue(ClaimTypes.Role)!, DataServer = principal.FindFirstValue(ClaimTypes.UserData)! }, principal.FindFirstValue(ClaimTypes.Dns)!, Convert.ToBoolean(principal.FindFirstValue(ClaimTypes.IsPersistent)!)); } public static RsaSecurityKey LoadRSAKey(string KeyPath) { if (!File.Exists(KeyPath)) { Console.WriteLine("Unable to load certificate from path: " + KeyPath); Console.WriteLine("---- Shutting down ----"); Environment.Exit(100); } string KeyText = File.ReadAllText(KeyPath); RSA rsa = RSA.Create(); rsa.ImportFromPem(KeyText.ToCharArray()); return new RsaSecurityKey(rsa); } } }