-
Notifications
You must be signed in to change notification settings - Fork 456
Description
Which version of Microsoft.IdentityModel are you using?
8.15.0
Where is the issue?
- M.IM.JsonWebTokens
- M.IM.KeyVaultExtensions
- M.IM.Logging
- M.IM.ManagedKeyVaultSecurityKey
- M.IM.Protocols
- M.IM.Protocols.OpenIdConnect
- M.IM.Protocols.SignedHttpRequest
- M.IM.Protocols.WsFederation
- M.IM.TestExtensions
- M.IM.Tokens
- M.IM.Tokens.Saml
- M.IM.Validators
- M.IM.Xml
- S.IM.Tokens.Jwt
- Other (please describe)
Is this a new or an existing app?
This is a new app/experiment.
Repro
// tokenValidationParameters configured with the IdP signing key(s)
var xml = Encoding.UTF8.GetString(Convert.FromBase64String(form["SAMLResponse"]));
var settings = new XmlReaderSettings {
DtdProcessing = DtdProcessing.Prohibit,
XmlResolver = null,
IgnoreWhitespace = false // preserve for XMLDSIG
};
using var reader = XmlReader.Create(new StringReader(xml), settings);
reader.MoveToContent();
reader.ReadToDescendant("Assertion", "urn:oasis:names:tc:SAML:2.0:assertion");
// Diagnostics show ancestor namespaces are in scope:
Debug.WriteLine(reader.LookupNamespace("saml")); // urn:oasis:names:tc:SAML:2.0:assertion
Debug.WriteLine(reader.LookupNamespace("xs")); // http://www.w3.org/2001/XMLSchema
Debug.WriteLine(reader.LookupNamespace("xsi")); // http://www.w3.org/2001/XMLSchema-instance
var handler = new Saml2SecurityTokenHandler();
var principal = handler.ValidateToken(reader, tokenValidationParameters, out var validatedToken);
// => throws XmlValidationException IDX30201: The 'Reference' did not validateExpected behavior
According to the Exclusive XML Canonicalization specification, when an ec:InclusiveNamespaces element is present, the prefixes listed in PrefixList must be treated inclusively, i.e., their namespace nodes (even if declared on ancestors) must be rendered in the canonicalized output of the signed subtree. Digest calculation over that canonicalized octet stream should therefore match the ds:DigestValue produced by the signer.
Given that the Response root declares xmlns:xs and xmlns:xsi, and the Assertion’s transform lists PrefixList="saml xs xsi", ValidateToken(XmlReader, ...) should successfully validate the ds:Reference without requiring local redeclaration of those prefixes on saml:Assertion.
Actual behavior
When validating a SAML 2.0 Assertion that is signed using Exclusive XML Canonicalization (http://www.w3.org/2001/10/xml-exc-c14n#) with an InclusiveNamespaces PrefixList="saml xs xsi", Saml2SecurityTokenHandler.ValidateToken(XmlReader, ...) fails with:
Microsoft.IdentityModel.Xml.XmlValidationException: IDX30201: The 'Reference' did not validate: '#Assertion-...', even though XmlReader.LookupNamespace("xs"/"xsi"/"saml") shows these prefixes are in scope at the saml:Assertion element.
If I redeclare xmlns:xs/xmlns:xsi/xmlns:saml directly on saml:Assertion (no other changes), the same call succeeds.
This strongly suggests the InclusiveNamespaces handling does not account for ancestor namespace nodes when validating from an XmlReader positioned at the assertion.
Possible solution
In the XmlReader validation path, when Exclusive‑C14N is selected and an InclusiveNamespaces PrefixList is present, ensure the canonicalizer materializes the namespace nodes for the listed prefixes from ancestor scope into the canonicalized subset for digest calculation.
Add regression tests that:
Use a Response with xmlns:xs/xsi on the root and an Assertion signed with Exclusive‑C14N + PrefixList="saml xs xsi".
Validate via ValidateToken(XmlReader, ...) advanced to saml:Assertion without local redeclarations (should pass).
Validate the same token after artificially moving the declarations off the root (should still pass if in scope via ancestors).
If implementation constraints require DOM, ensure the XmlReader path internally reconstructs the necessary in‑scope namespace nodes (or equivalent) before canonicalization.
Specs / references: W3C Exclusive C14N recommendation and interop examples explaining the role of InclusiveNamespaces.
Additional context / logs / screenshots / links to code
Test token (sanitized but structurally accurate)
<samlp:Response
xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"
xmlns:xs="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
Destination="https://xyz.com/default.aspx"
ID="FIMRSP_..."
IssueInstant="2026-02-12T14:39:44Z"
Version="2.0">
<saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">
https://abc.com
</saml:Issuer>
<samlp:Status>
<samlp:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success"/>
</samlp:Status>
<saml:Assertion ID="Assertion-uuid524b3f..." IssueInstant="2026-02-12T14:39:44Z" Version="2.0">
<saml:Issuer Format="urn:oasis:names:tc:SAML:2.0:nameid-format:entity">...</saml:Issuer>
<ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#" Id="uuid524b3f...">
<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="#Assertion-uuid524b3f...">
<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#">
<ec:InclusiveNamespaces xmlns:ec="http://www.w3.org/2001/10/xml-exc-c14n#" PrefixList="saml xs xsi"/>
</ds:Transform>
</ds:Transforms>
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<ds:DigestValue>kivS6o...yNY=</ds:DigestValue>
</ds:Reference>
</ds:SignedInfo>
<ds:SignatureValue>...</ds:SignatureValue>
</ds:Signature>
<!-- Subject / Conditions / Statements with xsi:type="xs:string" values -->
...
</saml:Assertion>
</samlp:Response>