Class SamlSpOptions
- Namespace
- Fdyay.IdentityServer.Saml.Sp
- Assembly
- Fdyay.IdentityServer.Saml.dll
Options for acting as a SAML 2.0 service provider toward an upstream identity provider.
public sealed class SamlSpOptions : RemoteAuthenticationOptions
- Inheritance
-
SamlSpOptions
- Inherited Members
Properties
AllowIdpInitiatedSignOn
Whether an assertion arriving for a request this server never made is accepted. Defaults to false.
public bool AllowIdpInitiatedSignOn { get; set; }
Property Value
Remarks
Off, because the correlation this gives up is doing real work: a solicited response is tied to state
this handler protected into RelayState when it sent the request, which is what says this browser
started this sign-on. An unsolicited assertion has none of that, so accepting one is a decision about a
partner IdP that a host makes deliberately.
Accepting them never means ignoring InResponseTo. An unsolicited response must name no request
at all; one that names a request, arriving with no state, is a solicited response somebody captured.
The sign-in is recorded against this scheme — the scheme item the external sign-in page reads — so the
provider's subject is looked up among this provider's users and no other's, whatever the assertion's attributes say.
Each assertion is accepted once (SAML Profiles §4.1.4.5). Both since 0.178.0: until then an unsolicited sign-in
recorded no scheme, and the page took the provider from the identity's own idp claim, which an attribute could
supply. Read since 0.59.0; documented until 0.178.0 as inert, which it was not.
ClockSkew
Tolerance applied when checking assertion time conditions. Defaults to 5 minutes.
public TimeSpan ClockSkew { get; set; }
Property Value
Remarks
Since 0.178.0 also an inbound LogoutRequest's: its NotOnOrAfter, and an IssueInstant neither
further ahead than this nor older than SamlOptions.DefaultRequestMaxAge and this together. An assertion's and a
logout request's ID is remembered until its own expiry plus this, which is when it would be refused anyway.
DecryptionCertificate
Our certificate for decrypting an EncryptedAssertion. Null when we publish no encryption key.
public X509Certificate2? DecryptionCertificate { get; set; }
Property Value
Remarks
Needs the private key: a partner IdP encrypts the content key to the public half.
IdpEntityId
The upstream IdP's entity ID (expected assertion issuer).
public string IdpEntityId { get; set; }
Property Value
IdpInitiatedReturnPath
Where the browser lands after an unsolicited sign-on. Defaults to /.
public PathString IdpInitiatedReturnPath { get; set; }
Property Value
Remarks
There is no return URL to honour: nothing on this site asked for the sign-on, so there is nowhere it
was going. The IdP's RelayState is not that destination either — it is a value the partner chose,
and navigating to it would make this a redirector for anyone who can reach the reply address.
The browser lands here with the identity in the external cookie; with the shipped pages it is the external sign-in
callback (/Account/ExternalLogin?handler=Callback) that turns it into a session. Read since 0.59.0; documented
until 0.178.0 as inert, which it was not.
IdpSigningCertificate
The upstream IdP's signing certificate, used to verify assertions.
public X509Certificate2 IdpSigningCertificate { get; set; }
Property Value
IdpSingleLogoutUrl
The upstream IdP's Single Logout URL (HTTP-Redirect binding). Required to initiate SP logout.
public string? IdpSingleLogoutUrl { get; set; }
Property Value
IdpSingleSignOnBinding
How the AuthnRequest reaches the upstream IdP's Single Sign-On URL: HTTP-Redirect (the default) or
HTTP-POST, as SamlConstants.Bindings names them.
public string IdpSingleSignOnBinding { get; set; }
Property Value
Remarks
Duende 8.0.1's service provider binds its request either way (its SamlProvider.BindingType). A posted
request is signed inside the XML rather than beside it, and arrives as a form the browser submits. Since 0.109.0.
IdpSingleSignOnUrl
The upstream IdP's Single Sign-On URL (HTTP-Redirect binding).
public string IdpSingleSignOnUrl { get; set; }
Property Value
MetadataPath
Where this service provider publishes its metadata. Defaults to /saml-metadata.
public PathString MetadataPath { get; set; }
Property Value
Remarks
Public information by definition — an entity id, a reply address, and the certificate a partner encrypts to. Set it to Empty to publish nothing, at the cost of handing the same values over by some other route.
NameIdClaimType
An additional claim type the SAML NameID is mapped to. Defaults to NameIdentifier, which the external identity carries either way.
public string NameIdClaimType { get; set; }
Property Value
Remarks
The NameID always arrives as NameIdentifier, because that is the type the shipped external-login page reads to find the provider subject and the type the sign-out path reads off the local principal to name the user back to the identity provider. Setting this adds a second claim of the given type for a deployment whose own external-login handling reads something else.
It used to replace the canonical type, which made every value but the default a registration that broke sign-in outright and sent a LogoutRequest naming nobody. Fixed in 0.52.0; a host that had set it and worked around the break needs no change, because the claim it asked for is still there.
OutboundSigningAlgorithm
The signature method this service provider signs with, as a URI. Null — the default — follows the key: RSA-SHA256, or ECDSA with the hash its curve pairs with.
public string? OutboundSigningAlgorithm { get; set; }
Property Value
Remarks
Duende 8.0.1's OutboundSigningAlgorithm, read for every message it signs: the AuthnRequest, the
LogoutRequest and the LogoutResponse. It has to be a method this server accepts — SHA-256, SHA-384 or
SHA-512, RSA or ECDSA to match SigningCertificate's key — so SHA-1, which Duende can still be told to
use, is refused at startup here. Since 0.109.0.
RequireEncryptedAssertion
Whether an assertion that arrives unencrypted is refused. Defaults to false.
public bool RequireEncryptedAssertion { get; set; }
Property Value
Remarks
Set it once the partner IdP is known to encrypt. Accepting either shape until then is the common case; accepting either shape afterwards lets whoever is on the path strip the encryption.
SignOutScheme
The scheme whose session an inbound LogoutRequest ends. Defaults to the sign-in scheme.
public string? SignOutScheme { get; set; }
Property Value
Remarks
The same shape OpenIdConnectOptions has, and for the same reason: the scheme an external identity
is written to is not the scheme that holds the session. When the identity provider ends the session at
its end and tells us, what has to go is the local session — and dropping that cookie is what makes the
rest of the sign-out sequence run, since 0.43.0 wraps the handler that holds it. Left null it falls back
to SignInScheme, which is the honest default for a handler
registered outside an identity server: there is no other session it knows of.
SignedOutCallbackPath
The path the IdP posts the LogoutResponse back to. Defaults to /signout-saml.
public PathString SignedOutCallbackPath { get; set; }
Property Value
SigningCertificate
Our certificate for signing the messages we send. Null to send them unsigned.
public X509Certificate2? SigningCertificate { get; set; }
Property Value
Remarks
Needs the private key. A partner identity provider that requires signed requests refuses an unsigned one, and until 0.70.0 there was no key here to sign with — so the three messages this handler sends all went out unsigned and the metadata said so.
All three, which is the part worth stating: the AuthnRequest that starts a sign-on, the
LogoutRequest that starts a logout, and the LogoutResponse that answers the provider's.
Signing the two requests and not the response would satisfy a partner's AuthnRequestsSigned and
still fail it at the end of a logout, which is the harder failure to attribute.
Setting it changes what the published metadata claims, because the two cannot honestly disagree: the
descriptor's AuthnRequestsSigned follows this, and the certificate is published as a signing
KeyDescriptor. Claiming to sign without publishing the key leaves a partner told to expect a
signature it has no way to verify.
The messages travel on the HTTP-Redirect binding, so the signature is the detached one on the query string (Bindings §3.4.4.1) rather than an enveloped XML signature — a DEFLATEd message in a URL has nowhere to carry one.
SpEntityId
Our entity ID as an SP (used as the AuthnRequest issuer and expected assertion audience).
public string SpEntityId { get; set; }
Property Value
StateDataFormat
Protects the relay state that correlates a response to its request.
public ISecureDataFormat<AuthenticationProperties> StateDataFormat { get; set; }
Property Value
Methods
Validate()
Refuses options the handler cannot run on, at startup rather than at the first sign-on.
public override void Validate()
Exceptions
- ArgumentException
SpEntityId, IdpEntityId or IdpSingleSignOnUrl is null or empty.
- ArgumentNullException
IdpSigningCertificate is null.
- InvalidOperationException
SigningCertificate has no private key; IdpSingleSignOnBinding is neither HTTP-Redirect nor HTTP-POST; or OutboundSigningAlgorithm is set with no signing certificate, or names a method its key cannot make.