.NET 6 WsFederation处理加密SAML时无令牌验证器错误求助
解决.NET 6 WsFederation处理加密SAML令牌时的"SecurityTokenException"问题
问题场景
我维护的.NET 6 Web应用基于联合IDP和SAML实现认证,此前使用Microsoft.AspNetCore.Authentication.WsFederation的AddWsFederation处理未加密SAML令牌完全正常。但IDP强制启用SAML加密(区别于仅SSL加密)后,接收加密令牌时抛出SecurityTokenException: No token validator was found for the given token异常。
排查发现:加密令牌导致认证管道无法识别令牌类型,虽能在SecurityTokenReceived回调中看到令牌载荷,但始终无法触发TokenValidationParameters中TokenDecryptionKey相关的解密逻辑。
问题根源
WsFederation中间件默认不会自动处理加密SAML断言,当前代码仅配置了SaveSigninToken,未设置解密密钥,导致中间件无法识别加密令牌并完成解密流程。
解决方案
1. 获取解密证书
从IDP处获取用于解密SAML加密断言的证书(通常是公钥证书,IDP用对应私钥加密断言),可通过文件、Base64字符串或证书存储加载。
2. 配置解密密钥与验证参数
在AddWsFederation配置中,为TokenValidationParameters添加TokenDecryptionKey,并确保证书正确转换为X509SecurityKey。
3. 可选:手动兜底解密
若自动解密仍失效,可在OnSecurityTokenReceived回调中手动解密令牌,再传递给后续管道处理。
修改后的代码示例
// 加载解密证书(示例:从文件加载,可替换为Base64或证书存储加载方式) var decryptionCert = new X509Certificate2("path/to/decryption-cert.pfx", "cert-password"); // 或从Base64字符串加载: // var certBytes = Convert.FromBase64String(Builder.Configuration["wsfed:decryptionCertBase64"]); // var decryptionCert = new X509Certificate2(certBytes); Builder.Services.AddAuthentication(sharedOptions => { sharedOptions.DefaultScheme = CookieAuthenticationDefaults.AuthenticationScheme; sharedOptions.DefaultChallengeScheme = WsFederationDefaults.AuthenticationScheme; sharedOptions.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme; }).AddWsFederation(options => { options.AllowUnsolicitedLogins = true; options.Wtrealm = Builder.Configuration["wsfed:realm"]; options.SignOutWreply = Builder.Configuration["wsfed:signout"]; options.MetadataAddress = Builder.Configuration["wsfed:metadata"]; options.RemoteSignOutPath = Builder.Configuration["wsfed:signoutpath"]; options.CorrelationCookie.SecurePolicy = CookieSecurePolicy.Always; // 配置TokenValidationParameters,添加解密密钥 options.TokenValidationParameters = new TokenValidationParameters { SaveSigninToken = true, TokenDecryptionKey = new X509SecurityKey(decryptionCert) }; options.Events.OnSecurityTokenReceived = context => { // 可选:自动解密失效时,手动解密令牌 // var tokenHandler = new SamlSecurityTokenHandler(); // var decryptionParams = new TokenDecryptionParameters // { // TokenDecryptionKeys = new List<SecurityKey> { new X509SecurityKey(decryptionCert) } // }; // var decryptedToken = tokenHandler.DecryptToken(context.Token, decryptionParams); // context.Token = tokenHandler.WriteToken(decryptedToken); return Task.CompletedTask; }; })
注意事项
- 确认解密证书与IDP使用的加密私钥配对,部分IDP可能使用与签名证书相同的密钥,但需以IDP文档为准。
- 若IDP元数据中包含加密密钥,
MetadataAddress加载后可能自动配置解密逻辑,无需手动添加,但需确保元数据地址可正常访问且包含加密密钥信息。 - 若使用文件加载证书,需确保应用程序进程拥有读取该文件的权限。
内容的提问来源于stack exchange,提问作者Dahlvash
相关产品推荐
相关产品推荐

