using SharedKernel; using System.Security.Claims; using System.Security.Cryptography; using System.Text; using Application.Abstractions.Authentication; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.JsonWebTokens; using Microsoft.IdentityModel.Tokens; namespace Infrastructure.Authentication; internal sealed class JwtTokenProvider(IOptions options) : IJwtTokenProvider { private readonly AppSettings.JwtSection _jwt = options.Value.JWT; public string CreateAccessToken(int memberID, string email, string? name) { var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwt.SecretKey)); var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); var claims = new List { new(JwtRegisteredClaimNames.Sub, memberID.ToString()), new(JwtRegisteredClaimNames.Email, email), new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()) }; if (!string.IsNullOrEmpty(name)) { claims.Add(new Claim(JwtRegisteredClaimNames.Name, name)); } var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(claims), Expires = DateTime.UtcNow.AddMinutes(_jwt.AccessTokenExpiration), SigningCredentials = credentials, Issuer = _jwt.Issuer, Audience = _jwt.Audience }; var handler = new JsonWebTokenHandler(); return handler.CreateToken(tokenDescriptor); } public string CreateRefreshToken() { var randomBytes = RandomNumberGenerator.GetBytes(64); return Convert.ToBase64String(randomBytes); } public string CreateOAuth2AccessToken(int applicationID, string clientID, int ownerMemberID, IEnumerable scopes, TimeSpan ttl) { var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jwt.SecretKey)); var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); var scopeList = scopes as IList ?? scopes.ToList(); var claims = new List { new(JwtRegisteredClaimNames.Sub, ownerMemberID.ToString()), new(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()), new("app_id", applicationID.ToString()), new("client_id", clientID), new("token_id", applicationID.ToString()), new("token_type", "oauth2"), new("scope", string.Join(' ', scopeList)) }; foreach (var s in scopeList) { claims.Add(new Claim("scp", s)); } var tokenDescriptor = new SecurityTokenDescriptor { Subject = new ClaimsIdentity(claims), Expires = DateTime.UtcNow.Add(ttl), SigningCredentials = credentials, Issuer = _jwt.Issuer, Audience = "antooza-public-api" }; var handler = new JsonWebTokenHandler(); return handler.CreateToken(tokenDescriptor); } }