The Name Identifier (NameID) is the unique identifier of the user in SAML. The NameID should be non-volatile and opaque, i.e. it should not contain personal information or information that is changeable over time, such as the user's name or email address. By default, our component will use the OpenIddict's "sub" claim as the NameID.
Our IdP component supports configuring the Subject NameID in assertions. This page covers the different ways of configuring the NameID format for all or specific service providers (SP), including how to set email or a custom NameID format.
Global NameID Format
To set the default NameId format for all service providers, you need to set the option DefaultNameIdentifierFormat
on the SamlIdpOptions
. By default, this value is urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
.
services.AddOpenIddict()
// Other configuration code removed for brevity
.AddSamlPlugin(options =>
{
options.DefaultNameIdentifierFormat = "urn:oasis:names:tc:SAML:2.0:nameid-format:unspecified";
});
NameID Format per SP
Since Rsk.Saml v5, we support setting the NameID Format per service provider. You can set the NameIdentifierFormat
property on the ServiceProvider
object.
This option will take precedence over the global configuration specified in SamlIdpOptions.DefaultNameIdentifierFormat
.
new ServiceProvider
{
// Other configuration code removed for brevity
NameIdentifierFormat = "urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified"
}
If you want to configure a NameId Format per SP but use a version older than Rsk.Saml v5, you will need to implement our ICustomSaml2SingleSignOnGenerator
.
This class performs custom generation logic for SAML Sign-on Response messages.
To override the Name Identifier, you must update the Assertion.Subject
property.
You can get information about the SP that made the initial sign-on request by using the ServiceProvider
property on the request
parameter.
public class CustomSamlSingleSignOnGenerator : ICustomSaml2SingleSignOnGenerator
{
public Task<Saml2Response> CreateResponse(Saml2Response response, ValidatedSamlMessage request)
{
if (request.ServiceProvider != null && request.ServiceProvider.EntityId == "SP1")
{
response.Assertion.Subject.NameId = new Saml2NameIdentifier("1234", new Uri("urn:oasis:names:tc:SAML:1.1:nameid-format:persistent"));
}
return Task.FromResult(response);
}
}
Lastly, you will need to register your custom implementation in the DI container, which must be done after calling our component, as the last registered implementation of the ICustomSaml2SingleSignOnGenerator
will be used.
services.AddTransient<ICustomSaml2SingleSignOnGenerator, CustomSamlSingleSignOnGenerator>();
NameID Format Requested by SP
The SP can optionally send a NameIdPolicy
element in an authentication request.
The requested format
in NameIdPolicy
will take precedence over the global and service provider specific configuration.
Email NameID Format
Generally, we recommend against using the user's email as the NameID, as it can expose personal information and may change over time. Unfortunately, some legacy service providers can only handle email NameIDs. In such a scenario, we recommend enabling email NameID per SP instead of setting it as the global option. Please check out the section "NameID Format per SP".
- Configure NameID format as "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
new ServiceProvider
{
// Other configuration code removed for brevity
NameIdentifierFormat = "urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress"
}
-
Ensure that the user has an email claim
-
Enable email IdentityResource. Note that email is not part of the
Profile
IdentityResource
services.AddIdentityServer()
// Other configuration code removed for brevity
.AddInMemoryIdentityResources(new IdentityResource[]
{
new IdentityResources.OpenId(),
new IdentityResources.Profile(),
new IdentityResources.Email()
});
- Authorize the Service Provider's Client record to access email resource
new Client
{
ClientId = "https://local.sp",
ClientName = "Local Client",
AllowedScopes = {"openid", "profile", "email"}
}
Custom NameID Format
If you have a custom NameId format, you will need to override our default implementation of ISamlNameIdGenerator
. You must implement the GenerateNameId
method to handle your custom format.
public class CustomNameIdGenerator : SamlNameIdGenerator
{
public override async Task<Saml2Subject> GenerateNameId(string subjectId, IList<Claim> userClaims, string defaultFormat, string requestedFormat = null)
{
const string customFormat = "urn:oasis:names:tc:SAML:2.0:nameid-format:transient";
if (requestedFormat == customFormat)
{
var nameIdValue = userClaims.FirstOrDefault(x => x.Type == "name")?.Value;
return new Saml2Subject(new Saml2NameIdentifier(nameIdValue, new Uri(customFormat)));
}
return await base.GenerateNameId(subjectId, userClaims, defaultFormat, requestedFormat);
}
}
Finally, you will need to register your custom implementation in the DI container, which must be done after calling our component, as the last registered implementation of ISamlNameIdGenerator
will be used.
services.AddTransient<ISamlNameIdGenerator, CustomNameIdGenerator>();