using System.IdentityModel.Tokens.Jwt; using System.Security.Claims; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.Extensions.Options; using YarpGateway.Config; namespace YarpGateway.Middleware; public class JwtTransformMiddleware { private readonly RequestDelegate _next; private readonly JwtConfig _jwtConfig; private readonly ILogger _logger; public JwtTransformMiddleware( RequestDelegate next, IOptions jwtConfig, ILogger logger ) { _next = next; _jwtConfig = jwtConfig.Value; _logger = logger; } public async Task InvokeAsync(HttpContext context) { var authHeader = context.Request.Headers["Authorization"].FirstOrDefault(); if (string.IsNullOrEmpty(authHeader) || !authHeader.StartsWith("Bearer ")) { await _next(context); return; } var token = authHeader.Substring("Bearer ".Length).Trim(); try { var jwtHandler = new JwtSecurityTokenHandler(); var jwtToken = jwtHandler.ReadJwtToken(token); var tenantId = jwtToken.Claims.FirstOrDefault(c => c.Type == "tenant")?.Value; var userId = jwtToken .Claims.FirstOrDefault(c => c.Type == ClaimTypes.NameIdentifier) ?.Value; var userName = jwtToken.Claims.FirstOrDefault(c => c.Type == ClaimTypes.Name)?.Value; var roles = jwtToken .Claims.Where(c => c.Type == ClaimTypes.Role) .Select(c => c.Value) .ToList(); if (!string.IsNullOrEmpty(tenantId)) { context.Request.Headers["X-Tenant-Id"] = tenantId; if (!string.IsNullOrEmpty(userId)) context.Request.Headers["X-User-Id"] = userId; if (!string.IsNullOrEmpty(userName)) context.Request.Headers["X-User-Name"] = userName; if (roles.Any()) context.Request.Headers["X-Roles"] = string.Join(",", roles); _logger.LogInformation( "JWT transformed - Tenant: {Tenant}, User: {User}", tenantId, userId ); } else { _logger.LogWarning("JWT missing tenant claim"); } } catch (Exception ex) { _logger.LogError(ex, "Failed to parse JWT token"); } await _next(context); } }