SAML 2.0 External Provider
IdentityServer includes a built-in SAML 2.0 Service Provider (SP) authentication handler that lets you authenticate users against an external SAML 2.0 Identity Provider (IdP). This is useful when you need to federate with enterprise identity systems such as ADFS, Shibboleth, or other SAML-compliant providers.
For the general external provider workflow (triggering authentication, handling callbacks, and managing cookies), see Integrating with External Providers.
Registering a SAML 2.0 External Provider
Section titled “Registering a SAML 2.0 External Provider”Call the AddSamlServiceProvider() extension method on the AuthenticationBuilder, just as you would register an OpenID Connect or other external provider:
builder.Services.AddIdentityServer();
builder.Services.AddAuthentication() .AddSamlServiceProvider(options => { options.SpEntityId = "https://my-app.example.com"; options.IdpEntityId = "https://idp.example.com"; options.SingleSignOnServiceUrl = "https://idp.example.com/saml2/sso"; options.SigningCertificatesBase64 = ["<base64-encoded IdP signing certificate>"]; });This registers a scheme named Saml2 (the default) that handles SAML 2.0 authentication flows. The scheme appears alongside any other external providers on the login page.
Custom Scheme Name
Section titled “Custom Scheme Name”To register multiple SAML providers, or to use a custom scheme name, pass the scheme name as the first argument:
builder.Services.AddAuthentication() .AddSamlServiceProvider("corporate-idp", options => { options.SpEntityId = "https://my-app.example.com"; options.IdpEntityId = "https://corporate-idp.example.com"; options.SingleSignOnServiceUrl = "https://corporate-idp.example.com/saml2/sso"; options.SigningCertificatesBase64 = ["<base64-encoded signing certificate>"]; });You can call AddSamlServiceProvider() multiple times with different scheme names to register several SAML IdPs side by side.
Configuration Options
Section titled “Configuration Options”The SamlServiceProviderOptions class controls how the SP handler communicates with the remote IdP.
Required Properties
Section titled “Required Properties”-
SpEntityIdThe entity ID of your application (the Service Provider). This is the identifier the IdP uses to recognize your application. -
IdpEntityIdThe entity ID of the remote SAML Identity Provider. -
SingleSignOnServiceUrlThe URL of the IdP’s Single Sign-On endpoint where authentication requests are sent.
Optional Properties
Section titled “Optional Properties”-
BindingTypeThe SAML binding to use when sending authentication requests. Accepted values areSamlBindingType.HttpRedirectandSamlBindingType.HttpPost. Defaults toSamlBindingType.HttpRedirect. -
SingleLogoutServiceUrlThe URL of the IdP’s Single Logout endpoint. When not set, outbound logout requests are disabled. Defaults tonull. -
SigningCertificatesBase64Base64-encoded X.509 certificates used to validate signatures from the IdP. You can provide multiple certificates to support key rotation. Defaults to empty list. -
AllowUnsolicitedAuthnResponseWhether to allow unsolicited (IdP-initiated) authentication responses. Whentrue, also setIdpInitiatedCallbackUrlto specify where users land after authentication. Defaults tofalse. -
IdpInitiatedCallbackUrlThe URL to redirect to after processing an unsolicited (IdP-initiated) authentication response. Required whenAllowUnsolicitedAuthnResponseistrue. Must be a relative path (e.g.,/ExternalLogin/Callback) or an absolute URL with http/https scheme. Defaults tonull. -
MaxRelayStateLengthMaximum length (in bytes) of the SAML RelayState value that will be persisted in authentication properties. RelayState values exceeding this limit are silently dropped to prevent cookie bloat. Defaults to1024. -
WantAssertionsSignedWhether assertions from the IdP must be signed. Defaults totrue. -
OutboundSigningAlgorithmThe XML signature algorithm used for outbound SAML requests. Defaults to RSA-SHA256. -
SpSigningCertificateBase64A base64-encoded PKCS#12 (PFX) certificate that includes the SP’s private key. The SP uses this certificate to sign outbound SAML messages such asAuthnRequestandLogoutResponse. You need to set this property when the remote IdP requires signed authentication requests, or when you enable single logout (SLO) viaSingleLogoutServiceUrl. Defaults tonull. -
SpSigningCertificatePasswordThe password for the PKCS#12 SP signing certificate set inSpSigningCertificateBase64. Leave thisnullif the certificate file has no password. Defaults tonull. -
ModulePathThe application-relative path prefix for the handler’s ACS and metadata endpoints. Defaults to"/Saml2". -
SignInSchemeThe authentication scheme used to persist the session after SAML authentication. Whennull, the default sign-in scheme is used. Defaults tonull. -
SignOutSchemeThe authentication scheme used when processing logout requests from the IdP. Whennull, the default sign-out scheme is used. Defaults tonull.
The BindingType property accepts values from the SamlBindingType enum:
SamlBindingType.HttpRedirect: sends the authentication request as a URL-encoded redirect (the default)SamlBindingType.HttpPost: sends the authentication request as an HTTP POST form submission
Validation
Section titled “Validation”The required properties (SpEntityId, IdpEntityId, and SingleSignOnServiceUrl) are validated eagerly at host startup. Any certificates listed in SigningCertificatesBase64 are also validated to confirm they can be loaded as X.509 certificates. If a required property is missing or a certificate is invalid, the application fails to start with a clear OptionsValidationException.
Static vs. Dynamic Providers
Section titled “Static vs. Dynamic Providers”Use this table to decide which registration approach fits your situation:
| Scenario | Approach |
|---|---|
| A small number of known SAML IdPs configured at deployment time | AddSamlServiceProvider() (this page) |
| Many IdPs managed at runtime, loaded from a database | Dynamic Providers with AddSamlDynamicProvider() |
Both approaches use the same underlying SAML SP handler. Static registration is simpler when you have a fixed set of providers and do not need runtime management.
For background on the IdP and SP roles in SAML 2.0, see IdP and SP Concepts.
IdP-Initiated SSO
Section titled “IdP-Initiated SSO”In a typical SP-initiated flow, your application redirects users to the external IdP for authentication. However, some enterprise scenarios require IdP-initiated SSO, where the external IdP sends users directly to your application without a prior authentication request.
To enable IdP-initiated SSO, set AllowUnsolicitedAuthnResponse to true and configure IdpInitiatedCallbackUrl to specify where users should land after authentication:
builder.Services.AddAuthentication() .AddSamlServiceProvider("corporate-idp", options => { options.SpEntityId = "https://my-app.example.com"; options.IdpEntityId = "https://corporate-idp.example.com"; options.SingleSignOnServiceUrl = "https://corporate-idp.example.com/saml2/sso"; options.SigningCertificatesBase64 = ["<base64-encoded signing certificate>"];
// Enable IdP-initiated SSO options.AllowUnsolicitedAuthnResponse = true; options.IdpInitiatedCallbackUrl = "/ExternalLogin/Callback";
options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; });Handling the Callback
Section titled “Handling the Callback”In your external login callback, you can access the authentication result and read the RelayState (if provided by the IdP):
// ExternalLoginController.cs or Callback.cshtml.cspublic async Task<IActionResult> Callback(){ var result = await HttpContext.AuthenticateAsync( IdentityServerConstants.ExternalCookieAuthenticationScheme);
if (result?.Succeeded != true) { throw new Exception("External authentication failed"); }
// The scheme name is available for identifying which provider was used result.Properties?.Items.TryGetValue("scheme", out var scheme);
// For IdP-initiated flows, the IdP may include RelayState for routing if (result.Properties?.Items.TryGetValue("relayState", out var relayState) == true && !string.IsNullOrEmpty(relayState)) { // Use relayState for app-specific routing (e.g., deep linking to a dashboard) // Note: Validate the relayState before using it for redirects }
// A default returnUrl is provided for IdP-initiated flows result.Properties?.Items.TryGetValue("returnUrl", out var returnUrl);
// Process the external login (create/update user, establish session, etc.) // ...}RelayState Handling
Section titled “RelayState Handling”When the external IdP includes a RelayState value in its response, IdentityServer surfaces it in AuthenticationProperties.Items["relayState"]. This allows your application to:
- Deep-link users to specific pages after authentication
- Pass application-specific context through the authentication flow
- Implement custom routing logic based on IdP-provided data
RelayState values larger than MaxRelayStateLength (default: 1024 bytes) are not persisted to prevent cookie size issues.