How to expose Federation Metadata for a Service Provider

Hi,

I need to expose Federation Metadata for my MVC Application (Service Provider), so that it can integrate with my client’s SSO system (Identity Provider). I’ve experimented with the following code, but the output looks suspicious as there are several TODO parts.

MVC Action:
public ActionResult FederationMetadata()
{
SAMLController.Initialize();
EntityDescriptor entityDescriptor = MetadataExporter.Export(SAMLController.Configuration, null);

XmlDocument xmlDocument = entityDescriptor.ToXml().OwnerDocument;
return this.Content(xmldocument.InnerXml, “text/xml”);
}

SAML.config:
<?xml version="1.0"?>

<ServiceProvider
Name=“<a href=“https://Dev.XXXXX.com/Authentication.ComponentSpace.Saml/””>https://Dev.XXXXX.com/Authentication.ComponentSpace.Saml/
LocalCertificateFile=“Certificates\ServiceProvider.pfx”
LocalCertificatePassword=“password”
AssertionConsumerServiceUrl=”~/Saml/AssertionConsumerService"
/>

<PartnerIdentityProvider
Name=“<a href=“http://Idp.XXXX.com/adfs/services/trust””>http://Idp.XXXX.com/adfs/services/trust"
PartnerCertificateFile=“Certificates\ADFS-Signing.cer”
SingleLogoutServiceUrl=“<a href=“https://Idp.XXXX.com/adfs/ls/””>https://Idp.XXXX.com/adfs/ls/
NameIDFormat=“urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress”
SingleSignOnServiceUrl=”<a href=“https://Idp.XXXX.com/adfs/ls/”“>https://Idp.XXXX.com/adfs/ls/
/>



Result:
<md:EntityDescriptor entityID=“https://dev.XXXX.com/Authentication.ComponentSpace.Saml/” ID=“_00003059-38d7-4772-b7f6-21d71bc7d1c8” xmlns:md=“urn:oasis:names:tc:SAML:2.0:metadata”>
<md:SPSSODescriptor ID=“_0000c478-0393-4177-a3be-e5158067c23b” protocolSupportEnumeration=“urn:oasis:names:tc:SAML:2.0:protocol” AuthnRequestsSigned=“false” WantAssertionsSigned=“false”>
md:KeyDescriptor
<KeyInfo xmlns=“http://www.w3.org/2000/09/xmldsig#”>

blah


</md:KeyDescriptor>
<md:SingleLogoutService Binding=“urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect” Location=“TODO: URL of SLO service endpoint” />
<md:SingleLogoutService Binding=“urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST” Location=“TODO: URL of SLO service endpoint” />
<md:AssertionConsumerService Binding=“urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST” Location=“TODO: URL of assertion consumer service endpoint” index=“0” isDefault=“true” />
</md:SPSSODescriptor>
</md:EntityDescriptor>

How do I specify the various TODO bits?

The TODO instructions are there because the MetadataExporter doesn’t have the URLs for your endpoints. These endpoints aren’t part of the saml.config.
You can either manually or programmatically update the metadata to include the URLs.
If you take a look at the high-level API ExampleServiceProvider project’s SAML/ExportMetadata.asxp page, you’ll see some code that replaces the placeholders with the actual URLs.
We intend to provide better support for metadata export in a future release.

For Reference, here’s how I got it to work:

public ActionResult FederationMetadata()
{
SAMLController.Initialize();

string partnerName = null;
var identityProviders = SAMLController.Configuration.PartnerIdentityProviderConfigurations;
if (identityProviders.Any())
{
partnerName = identityProviders.Keys.First();
}

EntityDescriptor entityDescriptor = MetadataExporter.Export(SAMLController.Configuration, partnerName);

// Replace placeholder URLs.
string assertionConsumerServiceUrl = Url.Action(“AssertionConsumerService”, “Saml”, null, Request?.Url?.Scheme);
string singleLogoutServiceUrl = Url.Action(“SloService”, “Saml”, null, Request?.Url?.Scheme);

entityDescriptor.SPSSODescriptors[0].AssertionConsumerServices.Clear();

var acsEndpoint = new IndexedEndpointType(SAMLIdentifiers.BindingURIs.HTTPPost, assertionConsumerServiceUrl, null, 0, true);
entityDescriptor.SPSSODescriptors[0].AssertionConsumerServices.Add(acsEndpoint);

entityDescriptor.SPSSODescriptors[0].SingleLogoutServices.Clear();

var logoutRedirectEndPoint = new EndpointType(SAMLIdentifiers.BindingURIs.HTTPRedirect, singleLogoutServiceUrl, null);
var logoutPostEndpoint = new EndpointType(SAMLIdentifiers.BindingURIs.HTTPPost, singleLogoutServiceUrl, null);
entityDescriptor.SPSSODescriptors[0].SingleLogoutServices.Add(logoutRedirectEndPoint);
entityDescriptor.SPSSODescriptors[0].SingleLogoutServices.Add(logoutPostEndpoint);

XmlDocument xmlDocument = entityDescriptor.ToXml().OwnerDocument;
var content = xmldocument.InnerXml;

var contentType = “text/xml”;
var bytes = Encoding.UTF8.GetBytes(content);
return File(bytes, contentType, “FederationMetadata.xml”);
}

Thanks for sharing your code.