using System.IdentityModel.Tokens.Jwt; using Microsoft.IdentityModel.Protocols; using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.Tokens; namespace DexDemoBackend; public class JwtValidator { private readonly AppConfig _config; private readonly HttpClient _httpClient; private ConfigurationManager? _configManager; public JwtValidator(AppConfig config) { _config = config; _httpClient = new HttpClient(new HttpClientHandler { ServerCertificateCustomValidationCallback = (_, _, _, _) => true }); } public async Task> ValidateToken(string token) { try { // Lazy init OIDC configuration manager _configManager ??= new ConfigurationManager( $"{_config.DexIssuer}.well-known/openid-configuration", new OpenIdConnectConfigurationRetriever(), new HttpDocumentRetriever(_httpClient) { RequireHttps = false } ); var oidcConfig = await _configManager.GetConfigurationAsync(CancellationToken.None); var validationParameters = new TokenValidationParameters { ValidateIssuer = true, ValidIssuer = _config.DexIssuer, ValidateAudience = false, ValidateLifetime = true, ValidateIssuerSigningKey = true, IssuerSigningKeys = oidcConfig.SigningKeys }; var handler = new JwtSecurityTokenHandler(); var principal = handler.ValidateToken(token, validationParameters, out _); var jwtToken = handler.ReadJwtToken(token); return jwtToken.Payload; } catch (Exception ex) { throw new UnauthorizedAccessException($"Token validation error: {ex.Message}", ex); } } }