The SAML protocol plugin is available for integrating the Identity Server with a Federation Server. As with all protocols, there is a request interface that is meant for a Service Provider or App (acting as a Relying Party) to integrate to, as well as a response interface that responds with SAML towards a Federation Server (acting as Service Provider towards the Identity Server, and as SSO server towards the Relying Party). This interaction is shown in the following sequence diagram:
Fig. 136 SAML Interaction Sequence
The SAML protocol of the Identity Server supports the generic SAML IDP initiated SSO flow, as well as an ADFS-specific IDP initiated SSO flow. In both cases the SAML POST binding is used.
To integrate the SAML protocol plugin, both the Service Provider (App) as well as the Federation Server need to be configured. This section will describe how the protocol works, how a Service Provider (App) can integrate, as well as how to setup a Federation Server using a generic SAML federation service, Ping Federate, and ADFS.
The following parameters can be provided to the authentication endpoint of the the Authentication Service as part of a SAML protocol request. Parameters must be provided in the query string of a GET request. Unknown parameters will be ignored.
serviceProviderId
client_id
forceAuthN
acr
freshness
target_url
Tip
If the downstream application is an OAuth client that will be accessed via SAML, the serviceProviderId can be omitted and the client_id can be used.
The authentication result is embedded in a generated HTML-page that uses JavaScript to auto-POST to the Assertion Consumer Service URL (acs-url) of the configured Federation Server. The parameters are as follows:
generic
adfs
In order for the Authentication Service to be able to communicate with a SAML Federation Server, the following must be configured:
See also
For information about how to create an authentication service profile, refer to the section about creating a new profile earlier in this guide.
When configuring the SAML protocol settings, the Authentication Service needs to know about the receiving end of the communications, as well as how to assert protocol message protection through digital signatures. The information that is required about the receiving Federation Server includes:
For message protection, the SAML protocol needs to be configured with a signing key.
Finally, there are a number of settings that can tweak the assertion generation procedure. The details of these settings can be found below.
The following configuration snippet is a template on how to configure the SAML protocol section of an Authentication protocol:
... <profiles> <profile> <type xmlns:auth="https://curity.se/ns/conf/profile/authentication"> auth:authentication-service </type> ... <protocol-id>${ID}</protocol-id> ... <protocols> <protocol> <id>${ID}</id> <saml> <signing-key>${reference-to-signing-key-id}</signing-key> <recipient-entity-id>${federation-service-entity-id}</recipient-entity-id> <acs-url>${federation-service-acs-url}</acs-url> <saml-federation-service-type>${federation-service-type}</saml-federation-service-type> <saml-clock-skew>${saml-clock-skew}</saml-clock-skew> <saml-assertion-time-to-live>${assertion-time-to-live}</saml-assertion-time-to-live> </saml> </protocol> ... </protocols> ... </profile> ... </profiles> ...
id
protocol-id
saml/signing-key
saml/recipient-entity-id
saml/acs-url
saml/saml-federation-service-type
genric
saml/saml-clock-skew
saml/saml-assertion-time-to-live
saml/saml-message-time-to-live
The SAML protocol uses the template plugins/protocol/saml/postback.vm to generate the HTML page that auto-POSTs the SAML Response message to the Federation Server. To change the template, create a file called postback.vm in the directory <template_dir>/third-party/protocol/saml/postback.vm and make any modifications that are needed.
plugins/protocol/saml/postback.vm
postback.vm
<template_dir>/third-party/protocol/saml/postback.vm
For debugging, it can be helpful to disable the auto-post to give you a chance to inspect the message before it is sent to the federation server. To do this, create a file called globals.vm in the <template_dir>/third-party-debug/base directory. In this template, set the $debugRedirect variable to true like this:
globals.vm
<template_dir>/third-party-debug/base
$debugRedirect
true
#set ($debugRedirect = true)
This will cause an interstitial page to be shown that contains the SAML message (both the encoded and decoded version) as well as the relay state.
Fig. 137 SAML Debugging
This technique of adding a global.vm template to third-party-debug and setting $debugRedirect can be used with any protocol, not just SAML.
global.vm
third-party-debug
For a Service Provider (App), that depends on SSO from a Federation Server, integration is kept as simple as possible. The Service Provider is registered with the Identity Server, see the section on configuring Service Providers. Doing so, it is assigned a Service Provider Id.
When making a request to authenticate a user, the Service Provider (App) redirects the user to the Authentication endpoint of the Identity Server, identifying itself with its Service Provider Id as parameter in the request. The authentication process ensures that the Federation Server gets a SAML Assertion with information about the authenticated user, and when this is accepted by the Federation Server, the user is redirected back to the Service Provider (App).
That URL that the authenticated user is redirected to, can be either the target-URL as configured with the Authentication Service (or maybe even a default URL that is configured at the Federation Server), but it can also be established as part of the initial request to the authentication endpoint of the Authentication Service. This means that the RelayState is generated from the request parameters, and provided to the Federation Server. It is then up to the Federation Server whether it understands this though.
As the SAML protocol will issue a SAML Assertion and provide that in an unsolicited SAML Response message to the Federation Server, both services need to be introduced to each other. At its minimum, the Authentication Service needs to exchange its EntityId as well as the signing certificate with the Federation Server at the receiving end. The EntityId is defined by the server’s Environment Id.
For information about configuring the Identity Server’s environment or the Crypto facility, refer to the sections Configuration Guide and Cryptography.
What follows, is information how to set up a PingFederate and ADFS Federation Server to be used by the Authentication Service.
The SAML integration protocol can be used with PingFederate from Ping Identity. In particular, the SAML 2.0 IdP-initiated Web SSO profile needs to be setup using a POST binding. The steps to do this are documented in the PingFederate manual, but consist of the following high-level steps:
Create a SAML 2.0 Identity Provider connection in PingFederate and an SP adapter that will integrate your app with PingFederate.
On the general connection information tab of the IdP connection
Use the Entity ID that corresponds to the environment/name as configured in the Identity Server. Enter the recipient-entity-id that was configured in the Identity Server as the Virtual Server IDs.
Entity ID
environment/name
recipient-entity-id
Virtual Server IDs
In the IdP connection, enabled the IdP-initiated SSO profile but not any of the others.
When configuring browser SSO, enable the POST binding but not the others.
Import and select the certificate that was configured in protocol instance’s saml/signing-key setting when configuring the security credential to be used for the PingFederate connection.
You can verify that the connection works by accessing the Authentication Service’s authenticate endpoint for the profile that is configured with the SAML integration protocol.
The SAML integration protocol can be used to use the Curity Identity Server as the authentication server in an AD FS environment. This is made possible by configuring the Curity Identity Server as a Claims Provider for the AD FS server.
Enter claims provider trust data manually
Use AD FS profile
Enable support for the Web SSO protocol
Set the Claims provider SAML 2.0 SSO URL to be the authentication endpoint. I.e. https://localhost:8443/authn/authenticate
Claims provider SAML 2.0 SSO URL
https://localhost:8443/authn/authenticate
Use a Claims provider trust identifier that corresponds to the environment/name as configured in the Curity Identity Server.
Claims provider trust identifier
Configure the certificate that corresponds to the signing-key configured in the Curity Identity Server.
signing-key
Send Claims Using a Custom Rule
c:[] => issue(claim = c);
Create a Claim Rule to passthrough all claims issued by the Curity Identity Server to a Relying Party
c:[Issuer == "se.curity"] => issue(claim = c);
Where se.curity corresponds to the environment/name as configured in the Curity Identity Server.
se.curity
Set the default Claims Provider for a Relying Party from powershell
Set-AdfsRelyingPartyTrust -TargetIdentifier "rp-entity-id" -ClaimsProviderName @("se.curity")
Where se.curity corresponds to the environment/name as configured in the Curity Identity Server and rp-entity-id is the configured identifier for the Relying Party.
rp-entity-id
When using IdP initiated SSO with ADFS, the form parameter RelayState is used. The value of the RelayState is a URL encoded string with the following components.
RelayState
Examples
Sending an unknown parameter foo
Authentication request https://login.example.com/authn/authenticate?serviceProviderId=app1&foo=bar Result: RelayState=RPID%3Dapp1%26RelayState%3Dfoo%253Dbar Data sent from ADFS to SAML Relying Party RelayState=foo%3Dbar
Authentication request
https://login.example.com/authn/authenticate?serviceProviderId=app1&foo=bar
Result:
RelayState=RPID%3Dapp1%26RelayState%3Dfoo%253Dbar
Data sent from ADFS to SAML Relying Party
RelayState=foo%3Dbar
Sending both target_url and an unknown parameter foo
Authentication request https://login.example.com/authn/authenticate?serviceProviderId=app1&foo=bar&target_url=https://localhost/ws-fed Result: RPID%3Dapp1%26wctx%3Dhttps%253A%252F%252Flocalhost%252Fws-fed%253Ffoo%253Dbar%26Relaystate%3Dhttps%253A%252F%252Flocalhost%252Fws-fed%253Ffoo%253Dbar Data sent from ADFS to a WS-Federation Relying Party wctx=https%3A%2F%2Flocalhost%2Fws-fed%3Ffoo%3Dbar Data sent from ADFS to a SAML Relying Party wctx=https%3A%2F%2Flocalhost%2Fws-fed%3Ffoo%3Dbar&RelayState=https%3A%2F%2Flocalhost%2Fws-fed%3Ffoo%3Dbar Note It is up to the application to handle the data received. Nor SAML nor ADFS specify the use of the data, but it could be used to for loading a specific endpoint in the RP, or similar.
https://login.example.com/authn/authenticate?serviceProviderId=app1&foo=bar&target_url=https://localhost/ws-fed
RPID%3Dapp1%26wctx%3Dhttps%253A%252F%252Flocalhost%252Fws-fed%253Ffoo%253Dbar%26Relaystate%3Dhttps%253A%252F%252Flocalhost%252Fws-fed%253Ffoo%253Dbar
Data sent from ADFS to a WS-Federation Relying Party
wctx=https%3A%2F%2Flocalhost%2Fws-fed%3Ffoo%3Dbar
Data sent from ADFS to a SAML Relying Party
wctx=https%3A%2F%2Flocalhost%2Fws-fed%3Ffoo%3Dbar&RelayState=https%3A%2F%2Flocalhost%2Fws-fed%3Ffoo%3Dbar
Note
It is up to the application to handle the data received. Nor SAML nor ADFS specify the use of the data, but it could be used to for loading a specific endpoint in the RP, or similar.
When using the SAML integration protocol, the integrating party can send SAML Logout Requests to logout the current authenticated session. The requests needs to conform to the SAML Single Logout Profile of the Profiles for the OASIS Security Assertion Markup Language (SAML) V2.0 (Section 4.4)
Single Logout Profile
Profiles for the OASIS Security Assertion Markup Language (SAML) V2.0
The logout is initiated by sending a LogoutRequest to <authentication-endpoint-path>/logout, below is an example request.
LogoutRequest
<authentication-endpoint-path>/logout
<samlp:LogoutRequest ID="_df7af98a-e872-457e-9ab5-9337b3680c1b" Version="2.0" IssueInstant="2020-05-15T05:41:03.269Z" Destination="https://login.example.com/saml/authn/authenticate/logout" Consent="urn:oasis:names:tc:SAML:2.0:consent:unspecified" xmlns:samlp="urn:oasis:names:tc:SAML:2.0:protocol"> <Issuer xmlns="urn:oasis:names:tc:SAML:2.0:assertion">http://fs.curityio.net/</Issuer> <NameID Format="urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified" xmlns="urn:oasis:names:tc:SAML:2.0:assertion">johndoe</NameID> <samlp:SessionIndex>_b2d5fe1d-bbb0-4644-a315-32728197fe60</samlp:SessionIndex> </samlp:LogoutRequest>
Curity Identity Server will validate that the Issuer is the recipient-entity-id of the protocol config, or one of the service-providers defined in the profile. If the request is valid, a LogoutResponse will be sent to the configured logout-service-url.
Issuer
service-providers
LogoutResponse
logout-service-url
The SessionIndex and NameID parameters are ignored, all SSO Sessions will be terminated.
SessionIndex
NameID
The LogoutResponse will contain a status code, and will be signed with the configured signing-key.
<saml2p:LogoutResponse Destination="https://fs.curityio.net/saml" ID="_89a4fa60-209f-47af-ba65-1b2959d02d13" InResponseTo="_df7af98a-e872-457e-9ab5-9337b3680c1b" IssueInstant="2020-05-15T05:41:03.276Z" Version="2.0" xmlns:saml2p="urn:oasis:names:tc:SAML:2.0:protocol"> <saml2:Issuer xmlns:saml2="urn:oasis:names:tc:SAML:2.0:assertion">se.curity</saml2:Issuer> <ds:Signature xmlns:ds="http://www.w3.org/2000/09/xmldsig#"> <ds:SignedInfo> <ds:CanonicalizationMethod Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> <ds:SignatureMethod Algorithm="http://www.w3.org/2001/04/xmldsig-more#rsa-sha256" /> <ds:Reference URI="#_89a4fa60-209f-47af-ba65-1b2959d02d13"> <ds:Transforms> <ds:Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature" /> <ds:Transform Algorithm="http://www.w3.org/2001/10/xml-exc-c14n#" /> </ds:Transforms> <ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256" /> <ds:DigestValue>GgDl0PDpNIr/OEex0KMlmZdphDnHFJSHxuxkL5I8GTI=</ds:DigestValue> </ds:Reference> </ds:SignedInfo> <ds:SignatureValue>tfcHN<snip>zS3fqQ==</ds:SignatureValue> <ds:KeyInfo> <ds:X509Data> <ds:X509Certificate>MIIDc<snip>KlQ==</ds:X509Certificate> </ds:X509Data> </ds:KeyInfo> </ds:Signature> <saml2p:Status> <saml2p:StatusCode Value="urn:oasis:names:tc:SAML:2.0:status:Success" /> </saml2p:Status> </saml2p:LogoutResponse>
The SAML SLO profile requires the SessionIndex parameter to be sent in a LogoutRequest. Curity Identity Server will just log out all browser sessions, and not take the sent SessionIndex into account. Curity Identity Server will however echo the sent SessionIndex in the LogoutResponse. Since some SAML Identity Providers might require the SessionIndex, it is recommended to enable the setting include-session-index-in-response.
include-session-index-in-response
A registered service-provider can use the simplified logout method by simply issuing a GET request with the query parameter serviceProviderId. This will terminate the session(s) and send an unsolicited LogoutResponse to the configured logout-service-url.
service-provider
GET
Not all SAML IdP support receiving unsolicited responses.