Customizations
A number of interfaces are exposed to enable custom implementations including session storage, certificate validation, and the HTTP-Post form.
Most applications do not require custom implementations. Only consider customizing session storage, certificate validation, or the HTTP-Post form if the defaults do not meet your deployment or security requirements.
ISsoSessionStore
The ISsoSessionStore interface supports storing SAML SSO session state.
The following implementations are provided:
- DistributedSsoSessionStore
- CookieSsoSessionStore
- AspNetSsoSessionStore
Distributed Cache Session Store
DistributedSsoSessionStore is the default implementation of ISsoSessionStore and it stores SSO session data in an IDistributedCache.
The default implementation of IDistributedCache caches to memory.
This is suitable for single server deployments.
For multi-server deployments without sticky sessions, an IDistributedCache implementation with a central repository such as the RedisCache or SqlServerCache should be used.
Distributed Cache Session Store Options
DistributedSsoSessionStoreOptions specifies options for DistributedSsoSessionStore.
CookieName
The session store index is stored in a SAML session cookie.
The default cookie name is saml-session.
CookieOptions
The cookie options apply to the SAML session cookie.
By default, the cookie properties are:
- HTTP only
- Secure
- Essential
- SameSite=None
Note
SAML protocol exchanges are, in most use cases, cross-site. Therefore, the cookie must be marked as SameSite=None.
The cookie's domain defaults to the host name. The following example sets the SAML session cookie's domain. This is necessary if SSO occurs across subdomains.
using ComponentSpace.Saml2.Bindings;
using ComponentSpace.Saml2.Session;
builder.Services.Configure<DistributedSsoSessionStoreOptions>(options =>
{
options.CookieOptions.Domain = "mydomain.com";
});
SlidingSessionExpiration
The sliding session expiration specifies the period of inactivity before the session state is deleted.
The default is 30 minutes.
The following example code sets the sliding session expiration to 60 minutes.
using ComponentSpace.Saml2.Bindings;
using ComponentSpace.Saml2.Session;
builder.Services.Configure<DistributedSsoSessionStoreOptions>(options =>
{
options.SlidingSessionExpiration = new TimeSpan(0, 60, 0);
});
Cookie Session Store
CookieSsoSessionStore stores the SSO session data in the cookie.
The cookie value is encrypted using the IDataProtector interface.
In a multi-server deployment, cipher keys should be stored in a central location.
The following example code specifies that SSO session state should be stored in the cookie.
using ComponentSpace.Saml2.Session;
builder.Services.AddScoped<ISsoSessionStore, CookieSsoSessionStore>();
Cookie Session Store Options
CookieSsoSessionStoreOptions specifies options for CookieSsoSessionStore.
CookieName
The session state is stored in a SAML session cookie.
The default cookie name is saml-session.
CookieOptions
The cookie options apply to the SAML session cookie.
By default, the cookie properties are:
- HTTP only
- Secure
- Essential
- SameSite=None
Note
SAML protocol exchanges are, in most use cases, cross-site. Therefore, the cookie must be marked as SameSite=None.
The cookie's domain defaults to the host name. The following example sets the SAML session cookie's domain. This is necessary if SSO occurs across subdomains.
using ComponentSpace.Saml2.Bindings;
using ComponentSpace.Saml2.Session;
builder.Services.Configure<CookieSsoSessionStoreOptions>(options =>
{
options.CookieOptions.Domain = "mydomain.com";
});
ASP.NET Cookie Session Store
AspNetSsoSessionStore stores the SSO session data in the ASP.NET session.
This requires ASP.NET sessions to be enabled.
The following example code specifies that SSO session state should be stored in the ASP.NET session.
using ComponentSpace.Saml2.Session;
builder.Services.AddScoped<ISsoSessionStore, AspNetSsoSessionStore>();
ICertificateValidator
The ICertificateValidator interface validates X.509 certificates to ensure they haven't expired or aren't otherwise invalid. This applies to both the local and partner X.509 certificates.
Certificates that fail validation are not used in SAML processing.
The default certificate validator checks for expired certificates which are considered invalid.
The following code turns off expired certificate checking.
using ComponentSpace.Saml2.Certificates;
builder.Services.Configure<CertificateValidationOptions>(options =>
{
options.EnableNotAfterCheck= false;
});
The following code removes all certificate validators so no certificate validation is performed.
The following code turns on certificate chain checking for CA-signed certificates.
using ComponentSpace.Saml2.Certificates;
builder.Services.Configure<CertificateValidationOptions>(options =>
{
options.EnableChainCheck = true;
});
Certificate Validation Options
CertificateValidationOptions specifies options for the ICertificateValidator implementation.
EnableNotBeforeCheck
Specifies whether checking the certificate's not-before date is enabled.
The default is true.
EnableNotAfterCheck
Specifies whether checking the certificate's not-after date is enabled.
The default is true.
EnableChainCheck
Specifies whether checking the certificate chain is enabled.
This check is ignored for self-signed certificates.
The default is false.
RevocationMode
The certificate revocation mode.
This only applies if EnableChainCheck is true.
The default is X509RevocationMode.NoCheck.
RevocationFlag
Specifies whether certificates in the chain should be checked for revocation.
This only applies if EnableChainCheck is true.
The default is X509RevocationFlag.EndCertificateOnly.
VerificationFlags
Specifies the conditions under which verification of certificates in the certificate chain should be conducted.
This only applies if EnableChainCheck is true.
The default is X509VerificationFlags.NoFlag.
UrlRetrievalTimeout
The maximum amount of time to be spent during online revocation verification or downloading the CRL.
This only applies if EnableChainCheck is true.
The default is 30 seconds.
IHttpPostForm
The IHttpPostForm interface creates the HTML form that's used with the HTTP-Post binding to send SAML messages.
HTML Template
The default HTML template is:
<html>
<body>
<noscript>
<p>
Since your browser doesn't support JavaScript,
you must press the Continue button to proceed.
</p>
</noscript>
{displayMessage}
<form id="samlform" action="{url}" method="post" target="{target}">
<div>
{hiddenFormVariables}
</div>
<noscript>
<div>
<input type="submit" value="Continue"/>
</div>
</noscript>
</form>
</body>
{javaScript}
</html>
The following substitution parameters are supported.
displayMessage
The message displayed in the browser while the HTML form is being posted.
url
The action URL for the HTTP Post.
target
The target for the HTTP Post (i.e. _self, _blank, _parent or _top).
hiddenFormVariables
The hidden form inputs containing the information to be posted.
javaScript
JavaScript used to automatically submit the HTML form.
<script>
function submitForm() {
document.forms.samlform.submit();
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", submitForm);
} else {
submitForm();
}
</script>
HTTP Post Form Options
HttpPostFormOptions specifies options for HttpPostForm.
FormTemplate
The HTML form template.
JavaScript
The JavaScript used to automatically submit the HTML form.
DisplayMessage
The message displayed in the browser while the HTML form is being posted.
Target
The HTML form target.
The default is _self.
HiddenFormVariableTemplate
The HTML hidden form variable template.
OtherFormVariables
Any non-SAML HTML hidden form variables to include in the HTML form.
ContentSecurityPolicy
The content security policy.
Content Security Policy
Content Security Policy (CSP) permits the control of resources, including JavaScript, that the browser may load. It helps detect and protect against Cross Site Scripting (XSS) and other forms of attack.
CSP is specified through a Content-Security-Policy header sent to the browser, or through an equivalent element.
By default, no Content-Security-Policy header is included. CSP is available if control of script execution is required for security or compliance reasons. Since the HTML form used for HTTP-Post includes inline JavaScript to automatically submit SAML messages, any CSP policy must allow this script to run for the form to function correctly.
Unsafe Inline
A policy allowing all inline script to load is possible but not recommended.
Nonce
A nonce may be added to the JavaScript to identify it and permit its loading through policy.
<script nonce="2BAC238EBCE24A24ABCC11132361D228">
function submitForm() {
document.forms.samlform.submit();
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", submitForm);
} else {
submitForm();
}
</script>
The corresponding policy would include the nonce.
A nonce may be included by specifying the HttpPostFormOptions.ContentSecurityPolicy.
using ComponentSpace.Saml2.Bindings.Post;
builder.Services.Configure<HttpPostFormOptions>(options =>
{
options.ContentSecurityPolicy =
HttpPostFormOptions.ContentSecurityPolicyOption.Nonce;
});
Hash
A hash may be used to identify the JavaScript and permit its loading through policy.
The corresponding policy would include the hash.
A hash may be included by specifying the HttpPostFormOptions.ContentSecurityPolicy.
using ComponentSpace.Saml2.Bindings.Post;
builder.Services.Configure<HttpPostFormOptions>(options =>
{
options.ContentSecurityPolicy =
HttpPostFormOptions.ContentSecurityPolicyOption.Hash;
});
Trusted Site
Rather than using inline script, a separate script file may be downloaded from a trusted site.
Typically, this will be the application site.
The script file contains the following JavaScript.
function submitForm() {
document.forms.samlform.submit();
}
if (document.readyState === "loading") {
document.addEventListener("DOMContentLoaded", submitForm);
} else {
submitForm();
}
The corresponding policy would include self (i.e. the origin site) as a trusted source.
Self may be included by specifying the HttpPostFormOptions.ContentSecurityPolicy and JavaScript source path.