using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; using System.Linq; using System.Security.Authentication; using System.Security.Claims; using System.Text; using System.Threading.Tasks; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; using XF.Domain.Dependency; using XF.Domain.Exceptions; using XF.Domain.Options; namespace XF.Domain.Authentications { public interface IJwtSecurity { string EncodeJwtToken(ICollection claims); void DecodeJwtToken(string jwt); } public class JwtSecurity : IJwtSecurity, IScopeDependency { private readonly IOptions _jwtConfigOptionAccessor; private readonly IHttpContextAccessor _contextAccessor; public JwtSecurity(IOptions jwtConfigOptionAccessor, IHttpContextAccessor contextAccessor) { _jwtConfigOptionAccessor = jwtConfigOptionAccessor; _contextAccessor = contextAccessor; } public string EncodeJwtToken(ICollection claims) { var jwtOptions = _jwtConfigOptionAccessor.Value.Jwt; if (jwtOptions == null) throw new ArgumentNullException(nameof(jwtOptions)); var bytes = Encoding.UTF8.GetBytes(jwtOptions.SecretKey); var securityKey = new SymmetricSecurityKey(bytes); var signingCredentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256Signature); var expired = DateTime.Now.AddMinutes(jwtOptions.Expired); var jwtSecurityToken = new JwtSecurityToken(jwtOptions.Issuer, jwtOptions.Audience, claims, DateTime.Now, expired, signingCredentials); var tokenHandler = new JwtSecurityTokenHandler(); var token = tokenHandler.WriteToken(jwtSecurityToken); return token; } public void DecodeJwtToken(string jwt) { var jwtOptions = _jwtConfigOptionAccessor.Value.Jwt; if (jwtOptions == null) throw new ArgumentNullException(nameof(jwtOptions)); JwtSecurityTokenHandler tokenHandler = new(); TokenValidationParameters valParam = new(); var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptions.SecretKey)); valParam.IssuerSigningKey = securityKey; valParam.ValidateIssuer = false; valParam.ValidateAudience = false; ClaimsPrincipal claimsPrincipal = tokenHandler.ValidateToken(jwt, valParam, out SecurityToken secToken); //foreach (var claim in claimsPrincipal.Claims) //{ // Console.WriteLine($"{claim.Type}={claim.Value}"); //} if (_contextAccessor.HttpContext is null) throw new AuthenticationException($"{nameof(_contextAccessor.HttpContext)} is null"); _contextAccessor.HttpContext.User = claimsPrincipal; } } }