SAML Configuration
This page documents the configuration options and models for the SAML 2.0 Identity Provider feature.
Call AddSaml() on the IdentityServer builder to enable SAML 2.0 support:
builder.Services.AddIdentityServer() .AddSaml();AddSaml() registers all SAML services and endpoints. You can call it with no arguments when all Service Provider configuration is managed via a store (the IdP’s entity ID and other defaults are derived automatically). Pass an options callback to configure protocol-level settings explicitly.
SamlOptions
Section titled “SamlOptions”SamlOptions controls the global behavior of the SAML 2.0 Identity Provider: how claims map to SAML attributes, how assertions are signed, how NameIDs are resolved, and what tolerances apply to timestamps and request lifetimes.
Access SamlOptions when calling AddSaml():
builder.Services.AddIdentityServer() .AddSaml(saml => { saml.DefaultSigningBehavior = SamlSigningBehavior.SignAssertion; saml.DefaultClockSkew = TimeSpan.FromMinutes(5); saml.WantAuthnRequestsSigned = true; });});Use SamlOptions when you need to set defaults that apply across all Service Providers (for example, a shared assertion
lifetime, a common set of AuthnContext mappings, or a global signing policy). Individual SPs can override most of these
defaults via their own SamlServiceProvider configuration.
Available options:
-
EntityIdThe SAML entity identifier for IdentityServer when acting as an IdP. Most deployments do not need to set this; the default value is derived from the host URL combined withEntityIdPath. Defaults to{host}/Saml2. -
EntityIdPathThe path segment appended to the host URL to form the defaultEntityId. Defaults to/Saml2. -
SigninStateLifetimeHow long sign-in request state is retained while the user authenticates. This controls the TTL for records in theISamlSigninStateStore. Defaults to 15 minutes. -
LogoutSessionLifetimeControls how long logout session tracking state is retained while front-channel logout completes. This controls the TTL for records in theISamlLogoutSessionStore. Defaults to 5 minutes. -
MaxMessageSizeMaximum size (in characters) of inbound SAML messages that IdentityServer will accept. Messages exceeding this limit are rejected. Defaults to 1,048,576 (1 MB). -
EndpointsConfigures the URL paths and supported bindings for SAML endpoints. SeeSamlEndpointOptionsbelow. -
MetadataConfigures metadata document generation. See SamlMetadataOptions below. -
WantAuthnRequestsSignedWhentrue, the IdP requires all AuthnRequests to be signed. Defaults totrue. -
RequireSignedLogoutResponsesWhentrue, IdentityServer requires LogoutResponse messages from SPs to be signed. Defaults totrue, per SAML 2.0 Profiles §4.4.4. Individual SPs can override this viaSamlServiceProvider.RequireSignedLogoutResponses. -
DefaultClaimMappingsMaps OIDC claim types to SAML attribute names. See Default Claim Mappings below. -
SupportedNameIdFormatsSupported NameID formats advertised by the IdP. Defaults to[ EmailAddress, Unspecified ].The NameID format determines how the user is identified to the SP. emailAddress uses the user’s email claim and is human-readable but is considered a good identifier. Unspecified uses the user’s
subclaim value. Inbound AuthnRequests are validated against the formats configured here; requests specifying an unsupported format are rejected. If you implement a custom NameID format viaISamlNameIdGenerator, add it to this list so that validation passes. See Name Identifiers for a full explanation. -
DefaultClockSkewClock skew tolerance for validating SAML message timestamps. Defaults to 5 minutes. -
DefaultRequestMaxAgeMaximum age for SAML AuthnRequests. Defaults to 5 minutes. -
DefaultSigningBehaviorDefault signing behavior for SAML responses. Defaults toSignAssertion. -
MaxRelayStateLengthMaximum length (in UTF-8 bytes) of the RelayState parameter. Defaults to 80.RelayState is an opaque string that an SP may include in its
AuthnRequestto preserve application state across the SSO round-trip. IdentityServer echoes it back unchanged so the SP can keep state that it needs for processing after authentication. The SAML specification mandates that RelayState MUST NOT exceed 80 bytes in length; this limit enforces that requirement. SeeRelayStatefor more context. -
DefaultAuthnContextMappingsMaps OIDCacr/amrvalues to SAMLAuthnContextClassRefURIs. Used when an SP requests a specific AuthnContext and IdentityServer needs to translate the user’s authentication method into the corresponding SAML identifier (a URI).Default mappings include
pwd→urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransportandexternal→urn:oasis:names:tc:SAML:2.0:ac:classes:unspecified.Per-SP overrides are set via
SamlServiceProvider.AuthnContextMappings. -
DefaultAssertionLifetimeHow long issued assertions are considered valid. Defaults to 5 minutes. Per-SP overrides are set viaSamlServiceProvider.AssertionLifetime. -
EmailNameIdClaimTypeThe claim type used to resolve an email-format NameID. Defaults to"email". Per-SP overrides are set viaSamlServiceProvider.EmailNameIdClaimType.
Error Inspector Callbacks
Section titled “Error Inspector Callbacks”These three optional callbacks let you observe and react to errors that occur while IdentityServer parses or validates incoming SAML messages. They’re particularly useful when debugging interoperability issues with a specific SP, because they give you access to the raw XML and error details before IdentityServer returns a failure response. The inspector may suppress or even fix errors by inspecting the XML node and setting the corresponding value in the parsed object. A common example of suppression is that while the SAML specification requires absolute URIs for all identifiers, many deployments use simple strings. This is an error that can be safely suppressed if needed.
None of these are required. When not set, IdentityServer handles errors using its default behavior.
-
AuthnRequestErrorInspectorA callback invoked when an error occurs while parsing or validating an incomingAuthnRequest. -
LogoutRequestErrorInspectorA callback invoked when an error occurs while parsing or validating an incomingLogoutRequest. -
LogoutResponseErrorInspectorA callback invoked when an error occurs while processing an incomingLogoutResponsefrom an SP during Single Logout (SLO).
Default Claim Mappings
Section titled “Default Claim Mappings”The default DefaultClaimMappings dictionary maps common OIDC claim types to SAML 2.0 attribute
names:
| Claim type | SAML attribute name |
|---|---|
name | http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name |
email | http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress |
role | http://schemas.xmlsoap.org/ws/2005/05/identity/role |
Claims not present in this mapping are still included in the assertion but use their original claim type as the attribute name.
Override mappings globally via SamlOptions.DefaultClaimMappings or per Service Provider via SamlServiceProvider.ClaimMappings.
SamlMetadataOptions
Section titled “SamlMetadataOptions”SamlMetadataOptions controls how the IdP metadata document is generated. Access it via SamlOptions.Metadata.
-
CacheDuration(TimeSpan) How long consumers (Service Providers and federation tools) should cache the metadata document before re-fetching it. This value is included as thecacheDurationattribute in the metadata XML. Defaults to 12 hours. -
ExpiryDuration(TimeSpan) How long the metadata document is considered valid. This value is used to compute thevalidUntilattribute in the metadata XML. After this time, consumers should discard any cached metadata. Defaults to 5 days.Using
CacheDurationandExpiryDurationtogether improves stability. With the default values, a consumer should refresh every 12 hours, but if the refresh fails, it can still continue using the cached metadata for up to 5 days.
builder.Services.AddIdentityServer() .AddSaml(saml => { saml.Metadata.CacheDuration = TimeSpan.FromHours(6); saml.Metadata.ExpiryDuration = TimeSpan.FromDays(7); });SamlEndpointOptions
Section titled “SamlEndpointOptions”SamlEndpointOptions configures the URL paths and supported bindings for all SAML protocol endpoints. Access it via SamlOptions.Endpoints.
| Property | Type | Default | Description |
|---|---|---|---|
SingleSignOnServicePath | string | "/Saml2/SSO" | Path for the SSO endpoint (receives AuthnRequests). |
SingleSignOnServiceBindings | ICollection<string> | [HttpRedirect, HttpPost] | Bindings advertised in metadata for the SSO endpoint. This controls what appears in the metadata document, not whether the endpoint accepts requests. |
SingleSignOnCallbackPath | string | "/Saml2/SSO/Callback" | Path for the SSO callback endpoint (after user authenticates). This is an internal endpoint that is not visible in the metadata document. |
SingleLogoutServicePath | string | "/Saml2/SLO" | Path for the SLO endpoint (receives LogoutRequests and LogoutResponses). |
SingleLogoutServiceBindings | ICollection<string> | [HttpRedirect, HttpPost] | Bindings advertised in metadata for the SLO endpoint. This controls what appears in the metadata document, not whether the endpoint accepts requests. |
SingleLogoutCallbackPath | string | "/Saml2/SLO/Callback" | Path for the SLO callback endpoint (completes the logout flow). This is an internal endpoint that is not visible in the metadata document. |
StateIdParameterName | string | "samlStateId" | Query string parameter name used to pass the SAML sign-in state identifier through the return URL in the redirect to the login page. |
builder.Services.AddIdentityServer() .AddSaml(saml => { saml.Endpoints.SingleSignOnServicePath = "/Saml2/SSO"; saml.Endpoints.SingleLogoutServicePath = "/Saml2/SLO"; });SamlServiceProvider Model
Section titled “SamlServiceProvider Model”SamlServiceProvider represents a registered SAML 2.0 Service Provider. Each SP has its own entity ID, ACS endpoints, signing certificates, and claim configuration. SPs can be registered statically in code or managed dynamically via a custom store.
Most properties on SamlServiceProvider are optional overrides of the global defaults set in SamlOptions. When a property is null, the corresponding SamlOptions default applies. This lets you configure sensible defaults once and only specify per-SP values where behavior needs to differ.
Available options:
-
EntityId(string) The SP’s entity identifier, as declared in its SAML metadata. Required. -
DisplayName(string) Human-readable name shown in logs and consent screens. Required. -
Description(string?) Optional description. Defaults tonull. -
Enabled(bool) Whenfalse, all SAML requests from this SP are rejected. Defaults totrue. -
ClockSkew(TimeSpan?) Per-SP clock skew override. UsesSamlOptions.DefaultClockSkewwhennull. Defaults tonull. -
RequestMaxAge(TimeSpan?) Per-SP request maximum age. UsesSamlOptions.DefaultRequestMaxAgewhennull. Defaults tonull. -
AssertionConsumerServiceUrls(ICollection<IndexedEndpoint>) ACS endpoints where SAML responses will be delivered. At least one is required. Each entry is anIndexedEndpointthat specifies the URL, binding, ordering index, and whether it is the default endpoint. SeeIndexedEndpointbelow.AssertionConsumerServiceUrls =[new(){Location = "https://sp.example.com/saml/acs",Binding = SamlBinding.HttpPost,Index = 0,IsDefault = true}] -
SingleLogoutServiceUrls(ICollection<SamlEndpointType>) The SP’s Single Logout Service endpoints. Each entry is aSamlEndpointTypethat pairs aLocation(URL) with aBinding(SamlBinding). You can configure multiple endpoints for different bindings. Currently only HTTP Redirect is supported for SLO. Required for SLO support. Defaults to an empty collection. SeeSamlEndpointTypebelow.SingleLogoutServiceUrls =[new(){Location = "https://sp.example.com/saml/slo",Binding = SamlBinding.HttpRedirect,}] -
RequireSignedAuthnRequests(bool?) Whentrue, unsigned AuthnRequests from this SP are rejected. Whennull, falls back to the globalSamlOptions.WantAuthnRequestsSigneddefault. Defaults tonull. -
RequireSignedLogoutResponses(bool?) Per-SP override for whether LogoutResponse messages must be signed. Whennull, falls back toSamlOptions.RequireSignedLogoutResponses. Defaults tonull. -
Certificates(ICollection<ServiceProviderCertificate>?) Certificates associated with this SP, with use annotations indicating whether each certificate is used for signature verification, encryption, or both. SeeServiceProviderCertificatebelow. Defaults tonull. -
AllowIdpInitiated(bool) Whentrue, IdP-initiated SSO is allowed for this SP. Defaults tofalse. -
ClaimMappings(IDictionary<string, string>) Per-SP claim-to-attribute mappings (internal claim name → SAML attribute URI) that overrideSamlOptions.DefaultClaimMappings. Defaults to{}. -
DefaultNameIdFormat(string) Default NameID format to use when the SP does not specify one. Defaults tourn:oasis:names:tc:SAML:1.1:nameid-format:unspecified. -
SigningBehavior(SamlSigningBehavior?) Per-SP signing behavior. UsesSamlOptions.DefaultSigningBehaviorwhennull. Defaults tonull. -
AssertionLifetime(TimeSpan?) Per-SP override for how long issued assertions are valid. UsesSamlOptions.DefaultAssertionLifetimewhennull. Defaults tonull. -
AllowedScopes(ICollection<string>) Identity resource names associated with this SP. Used to determine which identity resources (and their claim types) are available for inclusion in assertions. Only identity resource names are valid here - including API scope names causes resource validation to fail. Should not be empty. -
AuthnContextMappings(IDictionary<string, string>) Per-SP override foracr/amr→AuthnContextClassRefURI mappings. OverridesSamlOptions.DefaultAuthnContextMappingswhen set. Defaults to empty. -
RequestedClaimTypes(List<string>) Claim types this SP expects in assertions. Used to drive claim population for the SP. -
EmailNameIdClaimType(string?) Per-SP override for the claim used to resolve an email-format NameID. UsesSamlOptions.EmailNameIdClaimTypewhennull. Defaults tonull. -
AllowedSignatureAlgorithms(List<string>?) Signature algorithms this SP accepts. Whennull, the IdP’s default algorithm is used. Defaults tonull.
Enums and Value Types
Section titled “Enums and Value Types”SamlBinding
Section titled “SamlBinding”SAML bindings define how messages travel over HTTP. HTTP Redirect encodes the message into the URL query string, which works well for small messages such as AuthnRequest but is limited by URL length constraints. HTTP POST encodes the message in a hidden HTML form field and submits it automatically, making it the right choice for larger payloads (such as assertions with many attributes) and for keeping message content out of server access logs. See Bindings for a deeper explanation.
SamlBinding is used on SamlEndpointType (for each entry in SingleLogoutServiceUrls) and on the derived IndexedEndpoint (for each ACS endpoint in AssertionConsumerServiceUrls).
| Value | Description |
|---|---|
HttpRedirect | HTTP Redirect binding. The SAML message is sent as a query parameter. |
HttpPost | HTTP POST binding. The SAML message is sent in an HTML form. |
SamlSigningBehavior
Section titled “SamlSigningBehavior”SAML assertions and/or responses are signed with the IdP’s private key to prove their authenticity and prevent tampering. The signing behavior controls which XML elements carry a digital signature. SignResponse is the recommended choice for most deployments: it signs the response, providing integrity protection to the entire SAML message. See Assertions for background on why signing matters.
Controls what elements are signed in SAML responses:
| Value | Description |
|---|---|
DoNotSign | No signing. For testing only. Do not use in production. |
SignResponse | Signs the entire SAML <Response> element. Recommended. |
SignAssertion | Signs the <Assertion> element inside the response. |
SignBoth | Signs both the <Response> and the <Assertion>. Maximum security, larger messages. |
SamlEndpointType
Section titled “SamlEndpointType”SamlEndpointType is a record that pairs a URL location with a SAML binding. It is used as the element type of SamlServiceProvider.SingleLogoutServiceUrls to describe where the SP’s SLO service lives and which HTTP binding it accepts.
new SamlServiceProvider{ // ... SingleLogoutServiceUrls = [ new SamlEndpointType { Location = "https://sp.example.com/saml/slo", Binding = SamlBinding.HttpRedirect, } ]}Properties:
Location(string): The URL of the endpoint.Binding(SamlBinding): The HTTP binding the endpoint accepts.
IndexedEndpoint
Section titled “IndexedEndpoint”IndexedEndpoint represents a single Assertion Consumer Service (ACS) endpoint on a Service Provider. It extends the basic location-and-binding pair with an index (for ordering when multiple ACS endpoints are registered) and an optional default flag.
IndexedEndpoint is used as the element type of SamlServiceProvider.AssertionConsumerServiceUrls.
Properties:
Location(string): The ACS URL where SAML responses are delivered.Binding(SamlBinding): The HTTP binding the endpoint uses. Must beSamlBinding.HttpPostfor the ACS endpoint. HTTP Redirect is not supported for SAML Response delivery.Index(int): Integer index used to order multiple endpoints. Lower values take precedence.IsDefault(bool?): Whentrue, this endpoint is the default endpoint of its kind. When multiple endpoints are registered, exactly one should be marked as default.
Example:
AssertionConsumerServiceUrls =[ new IndexedEndpoint { Location = "https://sp.example.com/saml/acs", Binding = SamlBinding.HttpPost, Index = 0, IsDefault = true }]ServiceProviderCertificate
Section titled “ServiceProviderCertificate”ServiceProviderCertificate pairs an X.509 certificate with a use annotation that tells IdentityServer how to apply it for a given SP. Use it to configure signature verification certificates, encryption certificates, or certificates that serve both purposes.
Properties:
Certificate(X509Certificate2): The X.509 certificate. Required.Use(KeyUse): How the certificate is used. Defaults toKeyUse.Signing. SeeKeyUsebelow.
KeyUse
Section titled “KeyUse”KeyUse is a flags enum that controls how a ServiceProviderCertificate is applied.
| Value | Description |
|---|---|
Signing | Used to verify signatures on messages from this SP. |
Encryption | Used to encrypt assertions sent to this SP. |
Both | Used for both signature verification and encryption. Equivalent to Signing | Encryption. |
Caching Options
Section titled “Caching Options”The SAML add-on integrates with IdentityServer’s built-in caching infrastructure.
When you register a custom SP store with AddSamlServiceProviderStoreCache<T>(), IdentityServer wraps your store with
an in-memory cache to reduce repeated lookups.
The cache duration is controlled by SamlServiceProviderStoreExpiration on IdentityServerOptions.Caching:
SamlServiceProviderStoreExpiration(TimeSpan) How long SP lookups are cached when you useAddSamlServiceProviderStoreCache<T>(). Defaults to 15 minutes. This setting has no effect unless you callAddSamlServiceProviderStoreCache<T>().
builder.Services .AddIdentityServer(options => { options.Caching.SamlServiceProviderStoreExpiration = TimeSpan.FromMinutes(30); }) .AddSaml() .AddSamlServiceProviderStoreCache<MySamlServiceProviderStore>();IdP-Initiated SSO
Section titled “IdP-Initiated SSO”IdP-initiated SSO is a flow where the Identity Provider sends a SAML assertion to a Service Provider without first receiving an AuthnRequest. This is commonly used in portal pages (for example, a “My Apps” dashboard) where the user is already authenticated and clicks a tile to launch an SP application.
There is no built-in endpoint for IdP-initiated SSO. Instead, inject IIdpInitiatedSsoService into your own Razor Pages or controllers to generate and send the SAML response programmatically. See IIdpInitiatedSsoService for usage details.
To allow IdP-initiated SSO for a given SP, set AllowIdpInitiated = true on its SamlServiceProvider configuration:
new SamlServiceProvider{ EntityId = "https://sp.example.com", AllowIdpInitiated = true, // ...}For a working example, see the SAML 2.0 IdP-Initiated sample.