Table of Contents

Class SamlOptions

Namespace
Fdyay.IdentityServer.Saml.Configuration
Assembly
Fdyay.IdentityServer.Saml.dll

Options for the native SAML implementation.

public sealed class SamlOptions
Inheritance
SamlOptions
Inherited Members

Properties

AssertionLifetime

How long an issued assertion remains valid. Defaults to 5 minutes.

public TimeSpan AssertionLifetime { get; set; }

Property Value

TimeSpan

AuthnRequestErrorInspector

Called when an inbound AuthnRequest does not read cleanly, with every error found; null (the default) refuses it as before. Duende's AuthnRequestErrorInspector.

public Action<ReadErrorInspectorContext<SamlAuthnRequest>>? AuthnRequestErrorInspector { get; set; }

Property Value

Action<ReadErrorInspectorContext<SamlAuthnRequest>>

Remarks

The inspector may remove an error, or set its Ignore, and the request is then read and validated as any other; it may also set a corrected request as Data — a date in a partner's quirky format, say. Called only when there is an error, and at each read of the request (the sign-on, its resumption, the login page's context). Data.Issuer is unverified when it is called, as Duende warns: no decision should rest on it alone.

It cannot make a message trusted. The signature is checked after the inspector returns, over the message as received and against the provider the request finally names, and every check the validator makes is still made. In Duende's the signature is verified while reading, before the inspector runs, against the issuer as sent, and the request's TrustLevel is a settable property of the data the inspector is handed.

ClockSkew

Tolerance applied when checking assertion time conditions. Defaults to 5 minutes.

public TimeSpan ClockSkew { get; set; }

Property Value

TimeSpan

DefaultAuthnContextMappings

The acr and amr values and the AuthnContextClassRef each is issued as, for a provider with no mappings of its own. Defaults to Duende's two: pwd as PasswordProtectedTransport, external as unspecified.

public IReadOnlyDictionary<string, string> DefaultAuthnContextMappings { get; set; }

Property Value

IReadOnlyDictionary<string, string>

Remarks

The signed-in user's acr is looked up first, then each amr in the order the claims are held; the first found is issued, and unspecified when none is. Until 0.134.0 every assertion said PasswordProtectedTransport, however the user had signed in.

DefaultClaimMappings

The claim types and the attribute name each is issued as, for a provider with no mappings of its own. Defaults to Duende's three: name, email and role as the WS-Federation claim URIs.

public IReadOnlyDictionary<string, string> DefaultClaimMappings { get; set; }

Property Value

IReadOnlyDictionary<string, string>

Remarks

A claim type not listed is issued under its own name. role maps to http://schemas.xmlsoap.org/ws/2005/05/identity/role — without the claims/ segment the other two have — because that is the value Duende 8.0.1 ships. Until 0.141.0 the attributes were the session's name and email claims under those names.

DefaultRequestMaxAge

How old an AuthnRequest's IssueInstant may be. Defaults to 5 minutes, as Duende's does.

public TimeSpan DefaultRequestMaxAge { get; set; }

Property Value

TimeSpan

Remarks

Since 0.178.0 also how old a LogoutRequest may be when it reaches this server's service provider (SamlSpHandler), with SamlSpOptions.ClockSkew added there.

DefaultSigningBehavior

What is signed in a response to a provider that does not say; defaults to the assertion, as Duende's does.

public SamlSigningBehavior DefaultSigningBehavior { get; set; }

Property Value

SamlSigningBehavior

EmailNameIdClaimType

The claim an emailAddress NameID is read from. Defaults to email, as Duende's does.

public string EmailNameIdClaimType { get; set; }

Property Value

string

EnableIdpInitiatedSignOn

Whether this server will start a sign-on no service provider asked for. Defaults to false.

public bool EnableIdpInitiatedSignOn { get; set; }

Property Value

bool

Remarks

The IdP-initiated half of the Web SSO profile (§4.1.5): a link in this server's own portal that posts an assertion to a registered service provider. It is a capability rather than a default because the request that starts it carries no message this server can authenticate — that is what "unsolicited" means — so the decision to expose a route that signs a user into a service provider on a GET belongs to the host.

Read by saml/sso/initiate since 0.59.0, which answers nothing until it is set. Documented until 0.178.0 as inert, a note from the commit that declared it which outlived the commit that read it.

Endpoints

Where the SAML endpoints are served, and over which bindings. Duende's SamlOptions.Endpoints.

public SamlEndpointOptions Endpoints { get; set; }

Property Value

SamlEndpointOptions

EntityId

The IdP entity ID advertised in metadata and assertions. Defaults to the issuer when null.

public string? EntityId { get; set; }

Property Value

string

LogoutRequestErrorInspector

Called when an inbound LogoutRequest does not read cleanly; null (the default) refuses it as before. Duende's LogoutRequestErrorInspector, as AuthnRequestErrorInspector is for an AuthnRequest.

public Action<ReadErrorInspectorContext<SamlLogoutRequest>>? LogoutRequestErrorInspector { get; set; }

Property Value

Action<ReadErrorInspectorContext<SamlLogoutRequest>>

LogoutResponseErrorInspector

Called when an inbound LogoutResponse does not read cleanly; null (the default) refuses it as before. Duende's LogoutResponseErrorInspector, as AuthnRequestErrorInspector is for an AuthnRequest.

public Action<ReadErrorInspectorContext<SamlLogoutResponse>>? LogoutResponseErrorInspector { get; set; }

Property Value

Action<ReadErrorInspectorContext<SamlLogoutResponse>>

LogoutSessionLifetime

How long a single logout sequence may take before it is dropped. Defaults to 5 minutes, as Duende's LogoutSessionLifetime does.

public TimeSpan LogoutSessionLifetime { get; set; }

Property Value

TimeSpan

Remarks

Written onto each SamlLogoutSession as its ExpiresAt, for the same reason. Until 0.145.0 the in-memory store kept every sequence for a fixed five minutes.

MatchLogoutRequestToSession

Whether a verified LogoutRequest must name a SAML session this browser holds with the provider before it ends the session. Defaults to false: such a request ends the session, as it always has.

public bool MatchLogoutRequestToSession { get; set; }

Property Value

bool

Remarks

True runs Duende 8.0.1's LogoutRequestValidator.ValidateSessionAsync checks, measured, for every service provider that does not say otherwise with MatchLogoutRequestToSession. For a signed-in user, a request with no NameID, or whose NameID matches none of the provider's sessions here, is refused; one from a provider with no session here, or whose SessionIndex names none, is answered Success and ends nothing. Duende always runs them; Ours: off by default (decided 2026-10-14), because each changes what this server does with a verified request. New in 0.159.0.

MaxMessageSize

The longest inbound SAML message, in characters once decoded. Defaults to 1 MiB, as Duende's does.

public int MaxMessageSize { get; set; }

Property Value

int

Remarks

Checked before a POST-bound message is decoded and while a redirect-bound one is inflated, so a few kilobytes of deflated input cannot be made to expand without end, and again when the XML is loaded.

Since 0.178.0 at this server's service provider too — the SAMLResponse its assertion consumer reads and the LogoutRequest its single logout endpoint reads, and in SamlResponseValidator — where until then neither was bounded. Duende 8.0.1's service provider bounds neither, measured.

MaxRelayStateLength

The longest RelayState accepted, in UTF-8 bytes. Defaults to 80, the limit SAML Bindings §3.4.3 sets.

public int MaxRelayStateLength { get; set; }

Property Value

int

Metadata

The cacheDuration and validUntil published metadata carries. Duende's Metadata.

public SamlMetadataOptions Metadata { get; }

Property Value

SamlMetadataOptions

RequireHttpsServiceProviderUrls

Whether a registered service provider's reply and logout addresses must be https. Defaults to true.

public bool RequireHttpsServiceProviderUrls { get; set; }

Property Value

bool

Remarks

A SAML response carries a signed assertion, which is a bearer credential for whoever holds it, and the registration is the only thing that decides where it is delivered. Plaintext to a host that is not loopback puts that credential on a wire, so as of 0.71.0 such a registration is refused where it is read rather than served.

Loopback is exempt whatever this says, because a partner on the developer's own machine is the case https cannot be asked of, and a credential that never leaves the host is not on a wire. Setting this to false is the escape for a deployment terminating TLS somewhere this server cannot see — it is a statement that the plaintext hop is inside a boundary, not that the hop does not exist.

RequireSignedLogoutResponses

Whether a LogoutResponse must be signed. Defaults to true, as Duende's does.

public bool RequireSignedLogoutResponses { get; set; }

Property Value

bool

Remarks

Duende 8.0.1's SamlOptions.RequireSignedLogoutResponses, measured: read at the single logout endpoint for a LogoutResponse only, for every service provider that does not say otherwise with RequireSignedLogoutResponses. False lets an unsigned answer through; one that carries a signature is still held to it. Until 0.154.0 every LogoutResponse had to be signed, as it still must by default.

SigninStateLifetime

How long a sign-on waits for its user at the login page before the request it arrived with is dropped. Defaults to 15 minutes, as Duende's SigninStateLifetime does.

public TimeSpan SigninStateLifetime { get; set; }

Property Value

TimeSpan

Remarks

Written onto each SamlSignInState as its ExpiresAt when it is stored, so a store of the host's own can expire it without knowing these options, as Duende writes its ExpiresAtUtc. Until 0.145.0 the in-memory store kept every state for twenty minutes, and a store of the host's own was told nothing.

SigningCertificate

A certificate to sign with instead of this server's key material. Null (the default) signs with the server's current signing key, as Duende's does.

public X509Certificate2? SigningCertificate { get; set; }

Property Value

X509Certificate2

Remarks

Read by the default ISamlSigningService: when set, it signs every assertion, response and logout message and is the one key metadata publishes, and key rotation does not reach SAML. Null, the signing key is the one IKeyMaterialService signs tokens with — an RSA key wrapped in a certificate of its own — so it rotates with them. Duende has no such option; it is kept for a host whose partners pinned a certificate. Until 0.144.0 it was required.

SupportedNameIdFormats

The NameID formats a request may ask for, and metadata advertises, in this order. Defaults to emailAddress and unspecified, as Duende's does.

public ICollection<string> SupportedNameIdFormats { get; set; }

Property Value

ICollection<string>

Remarks

A request naming a format not listed here — or, naming none, from a provider whose DefaultNameIdFormat is not listed — is refused with InvalidNameIDPolicy. The default ISamlNameIdGenerator issues emailAddress from EmailNameIdClaimType and every other format from sub, so listing persistent or transient labels the subject id with that format, as Duende's does; a different value is a generator of the host's own.

WantAuthnRequestsSigned

Whether an AuthnRequest must be signed. Defaults to true, as Duende's does.

public bool WantAuthnRequestsSigned { get; set; }

Property Value

bool

Remarks

Duende 8.0.1's SamlOptions.WantAuthnRequestsSigned, measured: advertised in metadata as the IdP descriptor's WantAuthnRequestsSigned, and enforced for every service provider that does not say otherwise with RequireSignedAuthnRequests. A provider with no RequestSigningCertificate cannot sign, so it is refused unless it opts out.