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

SAML2断言含OneTimeUse条件验证失败(IDX13510)求助

解决SAML2断言含OneTimeUse条件的验证异常

问题背景

验证带有OneTimeUse条件的SAML2断言时触发以下异常,尝试通过选项类、扩展处理器等方式修改验证行为均未成功:

Microsoft.IdentityModel.Tokens.SecurityTokenValidationException: IDX13510: The Saml2SecurityToken cannot be validated because the Assertion specifies a OneTimeUse condition.Enforcement of the OneTimeUse condition is not supported by default.To customize the enforcement of OneTimeUse condition, extend Saml2SecurityTokenHandler and override ValidateOneTimeUseCondition.
at Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.ValidateOneTimeUseCondition(Saml2SecurityToken securityToken, TokenValidationParameters validationParameters)
at Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.ValidateConditions(Saml2SecurityToken samlToken, TokenValidationParameters validationParameters)
at ITfoxtec.Identity.Saml2.Tokens.Saml2ResponseSecurityTokenHandler.ValidateToken(SecurityToken token, String tokenString, Saml2Response saml2Response, Boolean detectReplayedTokens)
at ITfoxtec.Identity.Saml2.Saml2AuthnResponse.ReadClaimsIdentity(String tokenString, Boolean detectReplayedTokens)
at ITfoxtec.Identity.Saml2.Saml2AuthnResponse.Read(String xml, Boolean validateXmlSignature, Boolean detectReplayedTokens)
at ITfoxtec.Identity.Saml2.Saml2PostBinding.Read(HttpRequest request, Saml2Request saml2RequestResponse, String messageName, Boolean validateXmlSignature, Boolean detectReplayedTokens)
at ITfoxtec.Identity.Saml2.Saml2Binding`1.ReadSamlResponse(HttpRequest request, Saml2Response saml2Response)

对应的SAML响应示例:

<samlp:Response xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Version="2.0" ID="_381479691072dae3061c8eb476d8f638726d827456" IssueInstant="2023-01-04T19:59:55.431Z" Destination="https://p-dv-vm-tee8won:443/Relativity/Identity/98E1EA02C6824DB779469702E3C3A50DF55188D3"><saml:Issuer>https://capriza.github.io/samling/samling.html</saml:Issuer><samlp:Status><samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/></samlp:Status><saml:Assertion xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" Version="2.0" ID="_b4062517bccdf96dd61be6ad16374ba6aac7bccca6" IssueInstant="2023-01-04T19:59:55.383Z"><saml:Issuer>https://capriza.github.io/samling/samling.html</saml:Issuer><ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"><ds:SignedInfo><ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/><ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256"/><ds:Reference URI="#_b4062517bccdf96dd61be6ad16374ba6aac7bccca6"><ds:Transforms><ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/><ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#"/></ds:Transforms><ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/><ds:DigestValue>czTc3X2L2jmH8hZmbw8CnVbLGWIOCgWpQhLb6cMIRF4=</ds:DigestValue></ds:Reference></ds:SignedInfo><ds:SignatureValue>NH/nBTI88+D7KqA26IahTsf6bpXqSdBsGf/Bk4gvtJ9NGzfEJ14Pxh9fhYgq47begLqSY61Whoek6CQs908p8Qck37BFtvxR4gsWFULGIbb7ybsEMqajBR0pVDarxcC04bgXTa2nmMs2CO0lwl6lBMAEOQaf/03W8SxLSh2ovPQ=</ds:SignatureValue><ds:KeyInfo><ds:X509Data><ds:X509Certificate>MIICpzCCAhACCQDuFX0Db5iljDANBgkqhkiG9w0BAQsFADCBlzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCVBhbG8gQWx0bzEQMA4GA1UECgwHU2FtbGluZzEPMA0GA1UECwwGU2FsaW5nMRQwEgYDVQQDDAtjYXByaXphLmNvbTEmMCQGCSqGSIb3DQEJARYXZW5naW5lZXJpbmdAY2Fwcml6YS5jb20wHhcNMTgwNTE1MTgxMTEwWhcNMjgwNTEyMTgxMTEwWjCBlzELMAkGA1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExEjAQBgNVBAcMCVBhbG8gQWx0bzEQMA4GA1UECgwHU2FtbGluZzEPMA0GA1UECwwGU2FsaW5nMRQwEgYDVQQDDAtjYXByaXphLmNvbTEmMCQGCSqGSIb3DQEJARYXZW5naW5lZXJpbmdAY2Fwcml6YS5jb20wgZ8wDQYJKoZIhvcNAQEBBQADgY0AMIGJAoGBAJEBNDJKH5nXr0hZKcSNIY1l4HeYLPBEKJLXyAnoFTdgGrvi40YyIx9lHh0LbDVWCgxJp21BmKll0CkgmeKidvGlr3FUwtETro44L+SgmjiJNbftvFxhNkgA26O2GDQuBoQwgSiagVadWXwJKkodH8tx4ojBPYK1pBO8fHf3wOnxAgMBAAEwDQYJKoZIhvcNAQELBQADgYEACIylhvh6T758hcZjAQJiV7rMRg+Omb68iJI4L9f0cyBcJENR+1LQNgUGyFDMm9Wm9o81CuIKBnfpEE2Jfcs76YVWRJy5xJ11GFKJJ5T0NEB7txbUQPoJOeNoE736lF5vYw6YKp8fJqPW0L2PLWe9qTn8hxpdnjo3k6r5gXyl8tk=</ds:X509Certificate></ds:X509Data></ds:KeyInfo></ds:Signature><saml:Subject><saml:NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress">redactedemail@relativity.com</saml:NameID><saml:SubjectConfirmation Method="urn:oasis:names:tc:SAML:2.0:cm:bearer"><saml:SubjectConfirmationData NotOnOrAfter="2023-01-04T20:09:55.383Z" Recipient="https://p-dv-vm-tee8won:443/Relativity/Identity/98E1EA02C6824DB779469702E3C3A50DF55188D3"/></saml:SubjectConfirmation></saml:Subject><saml:Conditions NotBefore="2023-01-04T19:59:55.383Z" NotOnOrAfter="2023-01-04T20:09:55.383Z"><saml:AudienceRestriction><saml:Audience>https://p-dv-vm-tee8won/Relativity</saml:Audience></saml:AudienceRestriction><saml:OneTimeUse></saml:OneTimeUse></saml:Conditions><saml:AuthnStatement AuthnInstant="2023-01-04T19:59:55.383Z" SessionNotOnOrAfter="2023-01-04T20:09:55.381Z" SessionIndex="_samling_4122095_80192495"><saml:AuthnContext><saml:AuthnContextClassRef>urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified</saml:AuthnContextClassRef></saml:AuthnContext></saml:AuthnStatement></saml:Assertion></samlp:Response>

解决方案

由于使用的是ITfoxtec Identity SAML2库,需继承该库的Saml2ResponseSecurityTokenHandler并重写ValidateOneTimeUseCondition方法,替换默认处理器即可实现自定义验证逻辑。

1. 自定义SAML响应处理器

创建自定义处理器类,重写ValidateOneTimeUseCondition方法:

using ITfoxtec.Identity.Saml2.Tokens;
using Microsoft.IdentityModel.Tokens;
using Microsoft.IdentityModel.Tokens.Saml2;

public class CustomSaml2ResponseSecurityTokenHandler : Saml2ResponseSecurityTokenHandler
{
    protected override void ValidateOneTimeUseCondition(Saml2SecurityToken securityToken, TokenValidationParameters validationParameters)
    {
        // 方案1:完全跳过OneTimeUse验证(适合测试环境或完全信任IDP的场景)
        // 无需任何代码,直接跳过默认验证逻辑

        // 方案2:实现自定义一次性使用校验(生产环境推荐)
        // 示例:使用缓存存储已使用的断言ID,防止重复使用
        // var assertionId = securityToken.Assertion.Id.Value;
        // var cacheKey = $"SamlOneTimeUse_{assertionId}";
        // if (MemoryCache.Default.Contains(cacheKey))
        // {
        //     throw new SecurityTokenValidationException("该SAML断言已被使用过,无法重复验证");
        // }
        // // 按断言有效期设置缓存过期时间
        // var expiration = securityToken.Assertion.Conditions.NotOnOrAfter ?? DateTime.UtcNow.AddMinutes(10);
        // MemoryCache.Default.Add(cacheKey, true, expiration);
    }
}

2. 替换默认处理器

在服务配置中注册自定义处理器,替换默认的Saml2ResponseSecurityTokenHandler:

using ITfoxtec.Identity.Saml2;
using Microsoft.Extensions.DependencyInjection;

// 在Startup.cs或Program.cs的服务配置中添加
services.Configure<Saml2Configuration>(Configuration.GetSection("Saml2"))
    .AddSaml2()
    .AddSaml2SecurityTokenHandler<CustomSaml2ResponseSecurityTokenHandler>();

说明

之前修改选项类无效的原因是:OneTimeUse条件的验证逻辑硬编码在Saml2SecurityTokenHandler的方法中,必须通过重写对应方法才能修改行为。且由于使用了ITfoxtec的封装库,必须替换该库提供的处理器,而非直接修改Microsoft的基础处理器。

内容的提问来源于stack exchange,提问作者mtron

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.08 02:25:26