The Rock Solid Knowledge SAML SP component allows you to customize your metadata document. Some of the common use cases for customizing metadata include:
- Adding Organization and Contact details
- Adding
AttributeConsumingServices
- Changing the expiration time of the metadata
- Changing the maximum amount of time a consumer should cache the metadata
- Adding supported NameID formats
- Setting a default ACS endpoint
Metadata Configuration Settings
The startup configuration option ServiceProviderOptions.MetadataOptions
allows you to configure information such as your Organization and Contact details.
Check out the SP configuration options for more details.
.AddSaml2p("saml2p", options =>
{
// Other configuration code removed for brevity
options.ServiceProviderOptions.MetadataOptions = new ServiceProviderMetadataOptions
{
OrganizationDetails = new Organization
{
Name = "RSK",
Url = new Uri("https://www.rocksolidknowledge.com/")
}
};
});
Overriding Metadata Generation
If you cannot make the desired customization using the ServiceProviderOptions.MetadataOptions
configuration option, you can override the way the component generates metadata by implementing the IServiceProviderMetadataGenerator
interface.
This interface is what the component uses to generate the metadata configuration before it gets serialized.
public class CustomServiceProviderMetadataGenerator : IServiceProviderMetadataGenerator
{
private readonly IServiceProviderMetadataGenerator defaultGenerator;
public CustomServiceProviderMetadataGenerator(IServiceProviderMetadataGenerator defaultGenerator)
{
this.defaultGenerator = defaultGenerator ?? throw new ArgumentNullException(nameof(defaultGenerator));
}
public async Task<SamlEntityDescriptor> GenerateMetadata()
{
var metadata = await defaultGenerator.GenerateMetadata();
// edit the metadata, for example:
var descriptor = metadata.RoleDescriptors.First(x => x.GetType() == typeof(ServiceProviderSingleSignOnDescriptor)) as ServiceProviderSingleSignOnDescriptor;
descriptor.NameIdentifierFormats.Add(new Uri(SamlConstants.NameIdentifierFormats.Unspecified));
return metadata;
}
}
In order to create an instance of your new CustomServiceProviderMetadataGenerator
class, the component uses a factory abstraction. It is therefore necessary to implement the ISamlFactory
interface using the IServiceProviderMetadataGenerator
interface as the generic parameter.
public class CustomServiceProviderMetadataGeneratorFactory : ISamlFactory<IServiceProviderMetadataGenerator>
{
private readonly IHttpContextAccessor contextAccessor;
public CustomServiceProviderMetadataGeneratorFactory(IHttpContextAccessor contextAccessor)
{
this.contextAccessor = contextAccessor ?? throw new ArgumentNullException(nameof(contextAccessor));
}
public IServiceProviderMetadataGenerator Create(SamlSpOptions options)
{
return new CustomServiceProviderMetadataGenerator(new ServiceProviderMetadataGenerator(
contextAccessor,
new SamlSigningCertificateStore(new SamlOptionsKeyService(options)),
options));
}
}
having implemented the ISamlFactory
interface, you now need to register this factory in the DI container.
services.AddScoped<ISamlFactory<IServiceProviderMetadataGenerator>, CustomServiceProviderMetadataGeneratorFactory>();
Registering the factory with DI should be done after to the call to AddSaml2p
.