Setting up WebSSO Authentication with the IPP SSO SAML2 Artifact

IPP provides an ipp-sso-saml2 artifact, which offers SAML-based Single Sign-On (SSO) authentication. It uses the CSA_SSOSPI library to handle SAML2 authentication and integrates the IPP portal session with SAML2 authentication.

CSA_SSOSPI is the official client library for the Infinity external Identity Provider and can also handle SAML2 authentication with any other external Identity Provider.

Retrieving the Maven Artifact

The ipp-sso-saml2 artifact and its transitive dependencies need to be included in the WEB-INF/lib folder of your WAR deployment. Infinity archetypes include it in this folder by default if the dependency is added to the ipp-portal project.

Add the following dependency to the pom.xml file of your IPP WAR file:

<dependency>
   <groupId>com.infinity.bpm.ui.web</groupId>
   <artifactId>ipp-sso-saml2</artifactId>
   <version>9.2.0</version>
</dependency>

Configuration

This section describes the configuration required to use the ipp-sso-saml2 artifact.

Adding the CSA_SSOSPI Configuration Files

Download the following example configuration files and adapt them to fit the requirements of the specific Identity Provider:

These property files need to be located on the classpath at the following locations:

Adapt the URLs and client.id/portal.name properties in the websso.properties file. Change the certificate in the websso-keystore or use your own keystore.

The example websso.properties file uses an Identity Provider with name ipp-test using ClientId ipp-portal.

Keystore configuration

Configure a keystore to be used for signing, signature check and encryption if the corresponding features are enabled. Name this keystore websso-keystore.jks, so that it can be referenced from the example websso.properties.

SSO properties description

The following table gives an overview on SSO properties and their purpose:

Key

Value

Comments
skipUrlTypeList e.g. services,jsonservices,remoting

Comma separate list of URL patterns (without wildcard characters) from your filter / service configuration that you want to exclude from SSO. For example, if the request URL contains any of these words then SSO is skipped.

Default value is services,jsonservices,remoting.

excludeFileTypes e.g. .js,.css,.jpg,.gif

Specify the comma separated list of files type that you would like to exclude from SSO.

Default value is .js,.css,.jpg,.gif.

metadata.filename

This property is not required and should remain empty!

client.id

<<Tenant ID>>, e.g. ssoclient

This should match with the client id of the application. This property is essential for single logout to work properly.
portal.name e.g. My App This is not required by IdP, but required by SSO SPI for validating audience URL if validateAudienceUri is set to portal.name.
idpResponseEncrypted

true or false

Update this property to true only if you want to enable the client for Encryption. Once configured, client with look for EncryptedAssertion as part of SAMLv2 response and will decrypt that using its private key.

Default is set to true.

isSSOEnabled true or false

This flag must be set to true for enabling application for Single Sign On (SSO) with IdP

Default is set to true.

spInitiatedSSOEnabled true or false

It should be set to true, if you want to get redirected to IdP (for authentication) whenever you access the protected resource / page of your application.

Default is set to true.

samlTokenCachingEnabled true or false Should be set to true to avoid replay attack. SSO SPI stores the token in cache to validate against the replay attack, in case you are deploying in the cluster. Please refer the SSO SPI Release Notes to know how you can plugin your custom implementation to persist SAMLv2 tokens.

validateAudienceUri

none or client.id or acs.url or portal.name Valid values are none, client.id , acs.url and portal.name
  • none - Audience URI will not be validated. This is the default value.
  • client.id - Audience URI will be validated against client.id (same as Client ID configured in IdP).
  • acs.url - Audience URI will be validated against ACS URL configured in IdP.
  • portal.name - Audience URI will be validated against portal.name.
validateInResponseTo true or false

This is required when we want to validate AuthnRequest. During SAMLv2 flow, service providers send the AuthnRequest and if validateInResponseTo is set to true, it expects the AuthnRequest ID to be sent back in the SAMLv2 response as part of InResponseTo attribute or Response & SubjectConfirmation element.

Default is set to false.

processAsyncSessionTimeout true or false

If set to true, asynchronous logout request from IdP is processed and associated user session is invalidated for logging out the user.

Default is set to false.

sendAuthnRequest

true or false

If set to true, authentication request is sent to IdP.

Default is set to true.

sendLogoutRequest

true or false

If set to true, a logout request is sent to IdP. Setting this property to false means it will not send a logout request to IdP. This provides a quick logging out process and avoids a delay. No logout request means IdP will not trigger SingleLogout, i.e. it will clear only IdP user session and will not broadcast the logout request to other service providers.

Default is set to true.

signAuthnRequest true or false

If set to true, an authentication request is signed.

Default is set to true.

disableCacheDuringSSO true or false Default is set to false. If disableCacheDuringSSO is true and disableCacheRequestParamKey is not set explicitly then you will see a default "t" in the query string, e.g.
t=<<timestamp>>
This provision is added to avoid any issue due to browser caching.
disableCacheRequestParamKey e.g. t=<<timestamp>> i.e. t=234432565643

This key could be any alphanumeric string, e.g. idpnb, demosite or idpqa etc. This is appended in the IdP URL with the current timestamp for avoiding issues caused by browser caching. This is required only if disableCacheDuringSSO is true.

Default is "t".

home.url <http_or_https>://<host>:<port>/<context_root>/home.jsp, e.g.:
https://internal.csa.sungard.com:443/ssoclient/home.jsp
This is the landing page of your application. The property is read when RelayState is not part of the response sent by IdP. This could happen when the application didn't send the RelayState to the IdP or if IdP received it, but ignored it to avoid vulnerability.
encryption.property.file e.g. /encryption.properties Used for encrypting / decrypting the keystore password using jaspt API. Please make sure to keep the encryption.properties in the /WEB-INF/classes folder.
acsURL acs/POST.do You may keep the value as suggested in the Value column. In case you want to configure a different ACS URL, can change the value accordingly. ACS URL represents a resource / endpoint URL where SAMLv2 Response is posted by IdP.

Note
The ACS URL configured on the Service Provider Registration pages should end with the value configured here!

globalLogoutACSURL acs/globalLogoutACS.do You may keep the value as suggested in the Value column. However, in case you want to configure a different Global Logout ACS URL, can change the value accordingly. Upon Single Logout, IdP posts the SAMLv2 Logout Request to this endpoint / Resource URL.

Note
The Single Logout ACS URL configured on the Service Provider Registration pages should end with the value configured here.

sessionProcessorClassName Fully qualified name of the class implementing the SessionPrePostProcessor interface. Service provider need to implement the SessionPrePostProcessor interface. The implementing class need to provide the behavior for validating, creating and destroying the session.
providerName com.sungard.cs.websso.handler.saml.DefaultSAML2HttpPostHandler This provider sends authentication as well as logout request and validates the response from them.
samlBinding urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST We only support HTTP POST method presently, hence please keep the value as mentioned in the Value column.
protocol 1 Keep it as is. 1 refers to picking the HTTP POST handler.
excludeURLPattern .*authService.*|.*globalLogout.jsp You may configure the regular expression to exclude URLs that you want to exclude from SSO. This is in addition to the exclusion patterns listed in the websso.properties.
globalLogoutURL /logOff This is used as a trigger to initiate Single LogOut (SLO) with IdP. You may change it to match with your logout URI. Upon logout from your application, if the filter receives the request as http://host:port/myapp/logOff, it will trigger the SLO with IdP.
keyStoreType e.g. JKS or PKCS12 Provide JKS for java keystore (jks file) or PKCS12 for .p12 or .pfx keystore files
keyStoreFile

e.g. c:/sso/keystore.jks

Provide the absolute file path for signing keystore
keyStorePass e.g. changeit Provide signing the keystore password
privateKeyAlias e.g. test Provide the alias of the private key used for signing
privateKeyPass e.g. changeit Provide the password for the private key
certificateAlias e.g. test Should be the same as privateKeyAlias.
idpCertificateAlias e.g. test Certificate alias that refers to IdP certificate. Required only if your applicaiton is not using SAMLv2 metadata for SSO i.e. metadata.filename is not configured
encKeyStoreFile

e.g. c:/sso/keystore.jks

Provide the asolute file path for encryption keystore
encKeyStorePass e.g. changeit Provide the encryption keystore password

Error Page

Errors on logout or login will lead CSA_SSOSPI to redirect to {{/jsp/error.jsp}} which should be available in the Web deployment. You find an example error.jsp file here: error.jsp.

Multi-tenant support

For multi-tenant support the URL has to include the appID query parameter with a numeric value. This appID is used to load tenant specific settings from property files with the pattern websso_<appID>.properties. These tenant specific properties contain the ssoServiceURL for the IdP to authenticate against.

Please ensure the ServiceProvider ACS URL of the IdP also includes the same appID queryParameter so that the response is processed with the correct websso settings!

Adjusting the Configuration for SingleLogout (SLO)

To configure your SAML project for SingleLogout, perform the following changes in the websso.properties file:

  1. Remove /loggedOut.html from exludeURLPattern and define it for globalLogoutURL instead. The logoutPage property defines where to redirect the browser after successful logout.
    excludeURLPattern=.*authService.*|.*globalLogout.jsp|.*favicon.ico|.*jsp/error.jsp|.*loggedOut.html
    globalLogoutURL=/ippPortalLogout.jsp
    logoutPage=http://localhost:8181/ipp-portal-idp/
  2. Set the singleSignOutURL property to the correct URL on the IdP, e.g.:
    singleSignOutURL=https://someIdP.com/idp/ipp-test/globalLogout.html
  3. For most use cases it is recommended to set sendLogoutRequest to false, which speeds up the logout process by only logging out the current Portal's SAML session instead of triggering a global logout. Please note that a valid singleSignOutURL is still required. A call to this URL is made to invalidate the current session without triggering global logout.
    sendLogoutRequest=false

Using a global logout in a multi-tenant WebSSO setup

Note that if you use a global logout in a multi-tenant WebSSO setup, make sure the default tenant configuration (websso.properties) exists and has SSO disabled.

To enable SSO, enter the following in your websso.properties file:

isSSOEnabled=false
metadata.filename=

Configuring your Deployment Descriptor

Add the following filter and filter mapping to the web.xml file of your Web application, preferably as the first filter entry:

<!-- SamlSSO Filter -->
<filter>
   <filter-name>ipp-infinity-sso-filter</filter-name>
   <filter-class>com.infinity.bpm.ui.web.security.sso.saml.SamlSsoAuthFilter</filter-class>
</filter>
<filter-mapping>
   <filter-name>ipp-infinity-sso-filter</filter-name>
   <url-pattern>/*</url-pattern>
   <dispatcher>REQUEST</dispatcher>
   <dispatcher>FORWARD</dispatcher>
</filter-mapping>

This filter handles the saml2 authentication by using the SpringWebSSOFilter from the CSA_SSOSPI library.

Additionally add an entry for a SSO specific Authentication Provider Factory as context parameter:

<!-- SamlSSO AuthProvider -->
<context-param>
  <param-name>authenticationProviderFactory</param-name>
  <param-value>com.infinity.bpm.ui.web.security.sso.infinity.SSOAuthenticationProvider$Factory</param-value>
</context-param>

Configuring carnot.properties

Add the following entries or replace existing ones in your carnot.properties file:

Client.ServiceFactory = com.infinity.bpm.ui.web.security.sso.saml.client.SamlSsoSpringServiceFactory
Web.ServiceFactory = com.infinity.bpm.ui.web.security.sso.saml.client.SamlSsoSpringServiceFactory

Security.Authentication.Mode = principal
Security.Authorization.Mode = internal
Security.Authorization.SynchronizeOnLoad = false
Security.Principal.Validator = com.infinity.bpm.ui.web.security.sso.infinity.SsoPrincipalValidator
Security.Authorization.SynchronizationProvider = com.infinity.bpm.ui.web.security.sso.infinity.SSOUserSyncProvider

Configuring for Multi-tenant support

For multi-tenant support set property Security.Authentication.Sso.Saml.PartitionIdAttribute to the name of the SAML attribute containing the partitionId for IPP. The default is FirmName. If the attribute value is not contained in the SAML response, the default partition is used for all incoming SAML responses.

Security.Authentication.Sso.Saml.PartitionIdAttribute = FirmName

Specifying a list of attribute names

Use property Security.Authentication.Sso.Saml.UserAttributes to specify a comma separated list of attribute names in carnot.properties which should be mapped to IPP user properties, for example:

Security.Authentication.Sso.Saml.UserAttributes = MyTitle, FundRelationship

Setting a custom Portal SAML Session Expiration Time

To avoid a session expiration after the defined time of your SAML token, you can set a custom session expiration time via the property Security.Authentication.Sso.Saml.CustomSessionExpiry in your client-side carnot.properties file. Values less or equal 0 result in a session without expiry. The default value is null.

For example, to provide a 12h (720 minutes) Portal SAML session validity, set the following:

Security.Authentication.Sso.Saml.CustomSessionExpiry = 720

Example - Configuring a Multi-tenant IPP Portal War with IdP

This example demonstrates how to configure a multi-tenant IPP Portal war with IdP.

Configuration

Perform the following configuration steps:

  1. Use the default configuration from websso.properties
  2. Use the following tenant specific example configuration file: websso_1001.properties
  3. The tenant properties file contains an entry ssoServiceURL with a URL specific for this tenant, e.g.
    https://someIdP.com/idp/tenant1001?ClientID=ipp-portal
  4. The ServiceProvider entry on the IdP exists for the ClientID ipp-portal with the following ACS URL:
    https://localhost:8543/ipp-portal-war/acs/POST.do?appID=1001

Login Process

The login process is the following:

  1. Access the Portal URL with appID 1001
    https://localhost:8543/ipp-portal-war/?appID=1001
  2. Get forwarded to
    https://someIdP.com/idp/tenant1001?ClientID=ipp-portal
    and login.
  3. After a successful login the browser get forwarded to
    https://localhost:8543/ipp-portal-war/acs/POST.do?appID=1001
    This automatically will redirect to the logged-in IPP portal.

Authorization Integration with Infinity IdP

The aim of the IdP integration project (ipp-sso-iaf-idp) is to define standardized interfaces and provide lightweight implementations in IPP and/or IdP to allow for the following scenarios:

Note
Currently an unscoped organization is required in the model for the participant hierarchy to be synchronized to the IAF Infinity IdP correctly.

Retrieving the ipp-sso-iaf-idp Maven Artifact

The ipp-sso-iaf-idp artifact and its transitive dependencies need to be included in the WEB-INF/lib folder of your WAR deployment. IPP archetypes include it in WEB-INF/lib folder by default if the dependency is added to the ipp-portal project.

Add the following dependency to the pom.xml file of your IPP WAR file:

<dependency>
   <groupId>com.infinity.bpm.ui.web</groupId>
   <artifactId>ipp-sso-iaf-idp</artifactId>
   <version>9.2.0</version>
</dependency>

Configuration for Authorization Integration with Infinity IdP

Follow the configuration steps described for the ipp-sso-saml2 project (see section Configuration) and perform the following changes:

Changes in carnot.properties

Change the authorization mode to principal in your carnot.properties file:

Security.Authorization.Mode = principal

Changes in web.xml

Add the following entry in your web.xml file:

<!-- SamlSSO AuthProvider -->
<context-param>
  <param-name>authenticationProviderFactory</param-name>
  <param-value>com.infinity.bpm.ui.web.security.sso.iaf.DepartmentSyncSSOAuthenticationProvider$Factory</param-value>
</context-param>

Changes to the ipp-sso-iaf-idp spring resources

For a secured REST communication to IAF Infinity IdP the following configuration can be adapted:

A trust store containing the trusted certificate from the IAF Infinity IdPs https address needs to be located in websso-truststore.jks at the same location as websso-keystore.jks. The location and filename can be changed in ipp-sso-iaf-idp/src/main/resources/META-INF/spring/cxf_idp.xml.

The API key set up in the IAF Infinity IdP can be changed in the ipp-sso-iaf-idp/src/main/resources/META-INF/spring/idpapithrottling.properties file. The default is IPP_IdP_API_Key_iod-test.

Restriction on the Department Type Length

Please note that Organization Ids created as department types should not exceed 50 characters, otherwise the organization hierarchy synchronization fails. The DepartmentType is mapped to the Organization with the following format used to synchronize the organization hierarchy to IDP:

IPP_<modelId>_ MDL _<participantId>

For this reason make sure to keep modelId and partitipantId in all IdP models relatively short.

IAF Department Synchronization using IAF IdP SystemUser

IAF IdP requires a configured System User account. Once a System User account is set up, the credentials of the System User have to be set up for ipp-sso-iaf-idp via the META-INF/spring/idpapithrottling.properties file or the SystemUserCredentialsProvider SPI.

Setting up a System User Account

IAF IdP requires a System User account configured as described in the following sections.

Configuring Service Accounts

The value for the User Type must be set to 99, the label can be of any value. To edit the according fields, go to Site Administration > Customizations > Custom Fields > User Custom Fields and edit the User Type field to provide the necessary value:


Figure:

You need to select the User Type as Service Account in the user record:


Figure:

Note
An implement administrator must have checked the Enable Single-Factor System Accounts flag in your common service configurations in order for this feature to be allowed. This can only be done by an implement administration user, and cannot be set by a firm administrator.

Using Service Accounts

A "Service Account" user can only bypass MFA (multi-factor authentication) if REST services are used. If a "Service Account" user attempts to login from the user interface, then MFA will be still applicable. But, if the REST endpoint below is invoked, the user will get authenticated solely with login name and password and the REST end point will return a valid SessionID.

http(s)://<<host>>:<<port>>/<<idp_context_root>>/<<firm_name>>/rest/1.0/sessions (POST)

e.g.:

https://internal.csa.sungard.com/iaf_idp/Sample/rest/1.0/sessions
  1. Send Body Content as below:
    {"loginName":"<<Login_ID>>", "password":"<<Password>>"}
    e.g.
    {"loginName":"John.Doe", "password":"abc123"}
  2. Add Content Type as application/json.
  3. Add headers as below:

    Accept application/json
    X-SunGard-IdP-API-Key The API Key for the firm. Your firm administrator should be able to create one after logging in. Navigate to Site Administration > API Keys > Manage Keys and create a key. That key should be used as value.
    Note: Do not use the API-Key for the UI!

Post execution, once you receive a 200 response code, store the JSESSIONID cookie details, for example:

JSESSIONID=8C28C76CBE9E10789BE6DC573418D2C3

You can make further IdP REST calls by setting this SessionID as a cookie in the header, e.g.:

Header Name: Cookie, Value: JSESSIONID=8C28C76CBE9E10789BE6DC573418D2C3

Destroying the Service Account Session

After the service account job is done invoke the REST end point below to destroy it's session:

http(s)://<<host>>:<<port>>/<<idp_context_root>>/<<firm_name>>/rest/1.0/sessions (DELETE)

REST Calls

Make sure the following REST calls have been performed:

SystemUserCredentialsProvider SPI

Global default properties

If the SPI is not implemented by default the IAF IdP system user's username and password for all partitions are taken from the META-INF/spring/idpapithrottling.properties file.

X-SunGard-IdP-system-user-username=systemuser
X-SunGard-IdP-system-user-password=systemuser

Partition aware SystemUserCredentialsProvider SPI

You can provide different credentials for each partition by implementing the SystemUserCredentialsProvider SPI. The default values from idpapithrottling.properties file are no longer used if the SPI is implemented. So these defaults need to be handled as part of the SPI implementation.

package com.infinity.bpm.ui.web.security.sso.iaf;

public interface SystemUserCredentialsProvider
{
   public String getUsername(String partitionId);

   public String getPassword(String partitionId);
}

To implement the SPI create a file containing the qualified class name of the implementation at:

META-INF/services/com.infinity.bpm.ui.web.security.sso.iaf.SystemUserCredentialsProvider