Including XML in AttributeValue

I have a requirement to pass XML data in a CDATA section in an attribute in the SAMLResponse. I am using ASP.NET Core and have ComponentSpace v2.0.6. I’m using the low level API. I’ve seen some forum postings of examples of doing this for ASP.NET. But the same code doesn’t compile for the .NET Core. I can’t seem to find the methods/classes RegisterAttributeValueSerializer or XmlAttributeValueSerializer. What is the way to do this in .NET Core?

Here’s an example that I modified slightly from another forum posting.
ComponentSpace.Saml2.Assertions.AttributeType.RegisterAttributeValueSerializer(“ppc_plans”, SamlConstants.AttributeNameFormats.Basic, new XmlAttributeValueSerializer());
var xmlDocument = new XmlDocument();
xmldocument.LoadXml(vendorNetworkListXmlString);
samlAttribute = new SamlAttribute(“ppc_plans”, SAMLIdentifiers.AttributeNameFormats.Basic, “ppc_plans”);
samlAttribute.Values.Add(new AttributeValue(xmldocument.DocumentElement));
attributeStatement.Attributes.Add(samlAttribute);

Thank you

The following code demonstrates creating a SAML attribute whose value is a CDATA section.


// Create some test XML.
var xmlDocument = new XmlDocument()
{
PreserveWhitespace = true
};

xmlDocument.LoadXml(“”);

// Create the SAML attribute with the CDATA section as the attribute value.
// NB. The Type is cleared as it defaults to string.
var samlAttribute = new SamlAttribute()
{
Name = “test”,
AttributeValues = new List
{
new AttributeValue()
{
Type = null,
Data = new List()
{
xmlDocument.DocumentElement.FirstChild
}
}
}
};



The resultant XML is:


<saml:Attribute Name=“test”>
saml:AttributeValue

</saml:AttributeValue>
</saml:Attribute>


[quote]
ComponentSpace - 10/2/2019
The following code demonstrates creating a SAML attribute whose value is a CDATA section.


// Create some test XML.
var xmlDocument = new XmlDocument()
{
PreserveWhitespace = true
};

xmldocument.LoadXml("");

// Create the SAML attribute.
var samlAttribute = new SamlAttribute()
{
Name = "test"
};


// Add the CDATA section as the attribute value.
// NB. The Type is cleared as it defaults to string.
samlAttribute.AttributeValues.Add(new AttributeValue()
{
Type = null,
Data = new List()
{
xmldocument.DocumentElement.FirstChild
}
});



The resultant XML is:









[/quote]

Thank you that worked.
The only thing I would add is the following code, to add the SAML attribute into the SAML assertion. It took me awhile to figure this out since you can't use assertion.SetAttributeValue() as it doesn't take a SamlAttribute.

AttributeStatement statement = new AttributeStatement();
AttributeListItem listItem = new AttributeListItem();
listItem.SamlAttribute = samlAttribute;
statement.Attributes.Add(listItem);
assertion.Statements.Add(statement);

That’s true and thanks for sharing.

Note that for the great majority of use cases we recommend using the SAML high-level API. For an IdP this is the ISamlIdentityProvider interface. Using the high-level API, you don’t have to construct the SAML assertion as this is done for you.

[quote]
ComponentSpace - 10/2/2019
That's true and thanks for sharing.

Note that for the great majority of use cases we recommend using the SAML high-level API. For an IdP this is the ISamlIdentityProvider interface. Using the high-level API, you don't have to construct the SAML assertion as this is done for you.
[/quote]

I know, but for other reasons we can't use the high level API as this code is in a separate microservice docker container that is called from a variety of front ends.

Understood. It sounds like you fall into the set of use cases where calling the low-level API makes sense.

[quote]
ComponentSpace - 10/2/2019
Understood. It sounds like you fall into the set of use cases where calling the low-level API makes sense.
[/quote]

Even if I could use the high-level API, wouldn't I still need to use the low-level API code you posted above to add in my custom XML in a CDATA section of a SAML attribute?

No. The SAML high-level API accepts SamlAttribute objects. This is different from the SAML for ASP.NET API.
Here’s some code from the ExampleIdentityProvider project.


// Get the name of the logged in user.
var userName = User.Identity.Name;

// For demonstration purposes, include some claims.
var attributes = new List()
{
new SamlAttribute(ClaimTypes.Email, User.FindFirst(ClaimTypes.Email)?.Value),
new SamlAttribute(ClaimTypes.GivenName, User.FindFirst(ClaimTypes.GivenName)?.Value),
new SamlAttribute(ClaimTypes.Surname, User.FindFirst(ClaimTypes.Surname)?.Value),
};

var partnerName = _configuration[“PartnerName”];
var relayState = _configuration[“RelayState”];

// Initiate single sign-on to the service provider (IdP-initiated SSO)
// by sending a SAML response containing a SAML assertion to the SP.
// The optional relay state normally specifies the target URL once SSO completes.
await _samlIdentityProvider.InitiateSsoAsync(partnerName, userName, attributes, relayState);



These SAML attributes are string values but you could also construct a SAML attribute as shown in my previous reply. That’s what I did to test the code I included here.