You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

.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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.27 18:04:59