using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using System.Security.Cryptography; using System.Text; using AMREZ.EOP.Abstractions.Applications.Tenancy; using AMREZ.EOP.Abstractions.Security; using AMREZ.EOP.Infrastructures.Options; using Microsoft.AspNetCore.Http; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Tokens; namespace AMREZ.EOP.Infrastructures.Security; public sealed class JwtFactory : IJwtFactory { private readonly ITenantResolver _resolver; private readonly IHttpContextAccessor _http; private const string Issuer = "amrez.eop"; private const string Audience = "amrez.eop.clients"; private const int AccessMinutes = 10; public JwtFactory(ITenantResolver resolver, IHttpContextAccessor http) { _resolver = resolver; _http = http; } public (string token, DateTimeOffset expiresAt) CreateAccessToken(IEnumerable claims) { var tenantId = claims.FirstOrDefault(c => c.Type == "tenant_id")?.Value ?? throw new InvalidOperationException("tenant_id claim missing"); var keyBytes = SHA256.HashData(Encoding.UTF8.GetBytes(tenantId)); var creds = new SigningCredentials(new SymmetricSecurityKey(keyBytes), SecurityAlgorithms.HmacSha256); var now = DateTimeOffset.UtcNow; var exp = now.AddMinutes(AccessMinutes); var jwt = new JwtSecurityToken( issuer: Issuer, audience: Audience, claims: claims, notBefore: now.UtcDateTime, expires: exp.UtcDateTime, signingCredentials: creds ); return (new JwtSecurityTokenHandler().WriteToken(jwt), exp); } }