SAML
SAML 2.0 single sign-on and federation
The IG federation component implements SAML 2.0, to validate users and log them in to protected applications.
The SAML 2.0 standard describes the messages that providers exchange, and how they exchange them. SAML 2.0 enables web SSO, for example, where the service managing the user’s identity does not belong to the same organization and does not use the same software as the service that the user wants to access.
The following terms are used in SAML and federation:
-
Identity Provider (IDP): The service that manages the user identity, for example AM.
-
Service Provider (SP): The service that a user wants to access. IG acts as a SAML 2.0 SP for SSO, providing an interface to applications that don’t support SAML 2.0.
-
Circle of trust (CoT): An IDP and SP that participate in the federation.
When an IDP and an SP participate in a federation, they agree on what security information to exchange, and mutually configure access to each other’s services.
After an IDP authenticates a user, it provides the SP with SAML assertions that attest to which user is authenticated, when the authentication succeeded, how long the assertion is valid, and so on. The SP uses the SAML assertions to make authorization decisions, for example, to let an authenticated user complete a purchase that gets charged to the user’s account at the IDP.
The IDP and SP usually communicate about a user identified by a name identifier. In SP-initiated SSO and IDP-initiated SSO, the NameID format can be any format supported by the IDP. For more information, refer to Use a non-transient NameID format.
SAML assertions can be signed and encrypted. ForgeRock recommends using *SHA-256 variants (rsa-sha256 or ecdsa-sha256).
SAML assertions can contain configurable attribute values, such as user meta-information or anything else provided by the IDP. The attributes of a SAML assertion can contain one or more values, made available as a list of strings. Even if an attribute contains a single value, it is made available as a list of strings.
SAML in deployments with multiple instances of IG
IG uses a Java fedlet to implement SAML. When IG acts as a SAML service provider, the session information is stored in the fedlet, not the session cookie. In deployments that use multiple instances of IG as a SAML service provider, it is therefore necessary to set up sticky sessions so that requests always hit the instance where the SAML interaction was started.
For information, refer to Session state considerations in AM’s SAML v2.0 guide.
About SP-initiated SSO
SP-initiated SSO occurs when a user attempts to access a protected application directly through the SP. Because the user’s federated identity is managed by the IDP, the SP sends a SAML authentication request to the IDP. After the IDP authenticates the user, it provides the SP with a SAML assertion for the user.
The following sequence diagram shows the flow of information in SP-initiated SSO, when IG acts as a SAML 2.0 SP:
About IDP-initiated SSO
IDP-initiated SSO occurs when a user attempts to access a protected application, using the IDP for authentication. The IDP sends an unsolicited authentication statement to the SP.
Before IDP-initiated SSO can occur:
-
The user must access a link on the IDP that refers to the remote SP.
-
The user must authenticate to the IDP.
-
The IDP must be configured with links that refer to the SP.
The following sequence diagram shows the flow of information in IDP-initiated SSO when IG acts as a SAML 2.0 SP:
Set up federation with unsigned/unencrypted assertions
For examples of the federation configuration files, refer to Example fedlet files. To set up multiple SPs, work through this section, and then SAML 2.0 and multiple applications.
-
Set up the network:
Add
sp.example.com
to your/etc/hosts
file:127.0.0.1 localhost am.example.com ig.example.com app.example.com sp.example.com
Traffic to the application is proxied through IG, using the host name
sp.example.com
. -
Configure a Java Fedlet:
The SAML library component validates the SP’s AssertionConsumerService Location against the incoming IDP SAML Assertion, based on the request information, including the port. In
sp.xml
, always specify the port in the Location value ofAssertionConsumerService
, even when using defaults of 443 or 80, as follows:<AssertionConsumerService isDefault="true" index="0" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="https://sp.example.com:443/fedletapplication" />
For more information about Java Fedlets, refer to Creating and configuring the fedlet in AM’s SAML v2.0 guide.
-
Copy and unzip the fedlet zip file,
Fedlet-7.3.0.zip
, delivered with the AM installation, into a local directory.$ unzip $HOME/openam/Fedlet-7.3.0.zip Archive: Fedlet-7.3.0.zip creating: conf/ inflating: README inflating: conf/FederationConfig.properties inflating: conf/fedlet.cot-template inflating: conf/idp-extended.xml-template inflating: conf/sp-extended.xml-template inflating: conf/sp.xml-template inflating: fedlet.war
-
For AM 6.5.2 and earlier versions, add the following lines to
FederationConfig.properties
:# Specifies implementation for # org.forgerock.openam.federation.plugin.rooturl.RootUrlProvider interface. # This property defines the default base url provider. com.sun.identity.plugin.root.url.class.default=org.forgerock.openam.federation.plugin.rooturl.impl.FedletRootUrlProvider
-
In each file, search and replace the following properties:
Replace this With this IDP_ENTITY_ID
openam
FEDLET_ENTITY_ID
sp
FEDLET_PROTOCOL://FEDLET_HOST:FEDLET_PORT/FEDLET_DEPLOY_URI
http://sp.example.com:8080/saml
fedletcot
andFEDLET_COT
Circle of Trust
sp.example.com:8080/saml/fedletapplication
sp.example.com:8080/saml/fedletapplication/metaAlias/sp
-
Save the files as .xml, without the
-template
extension, so that the directory looks like this:conf ├── FederationConfig.properties ├── fedlet.cot ├── idp-extended.xml ├── sp-extended.xml └── sp.xml
By default, AM as an IDP uses the NameID format
urn:oasis:names:tc:SAML:2.0:nameid-format:transient
to communicate about a user. For information about using a different NameID format, refer to Use a Non-Transient NameID Format.
-
-
Set up AM:
-
Select Identities, select the user
demo
, and change the last name toCh4ng31t
. Note that, for this example, the last name must be the same as the password. -
Select Applications > Federation > Circles of Trust, and add a circle of trust called
Circle of Trust
, with the default settings. -
Set up a remote service provider:
-
Select Applications > Federation > Entity Providers, and add a remote entity provider.
-
Drag in or import
sp.xml
created in the previous step. -
Select Circles of Trust:
Circle of Trust
.
-
-
Set up a hosted identity provider:
-
Select Applications > Federation > Entity Providers, and add a hosted entity provider with the following values:
-
Entity ID:
openam
-
Entity Provider Base URL:
http://am.example.com:8088/openam
-
Identity Provider Meta Alias:
idp
-
Circles of Trust:
Circle of Trust
-
-
Select Assertion Processing > Attribute Mapper, map the following SAML attribute keys and values, and then save your changes:
-
SAML Attribute:
cn
, Local Attribute:cn
-
SAML Attribute:
sn
, Local Attribute:sn
-
-
In a terminal, export the XML-based metadata for the IDP:
$ curl -v \ --output idp.xml \ "http://am.example.com:8088/openam/saml2/jsp/exportmetadata.jsp?entityid=openam"
The
idp.xml
file is created locally.
-
-
-
Set up IG:
-
Copy the edited fedlet files, and the exported
idp.xml
file into the IG configuration, at$HOME/.openig/SAML
.$ ls -l $HOME/.openig/SAML FederationConfig.properties fedlet.cot idp-extended.xml idp.xml sp-extended.xml sp.xml
-
In
config.json
, comment out or remove thebaseURI
:{ "handler": { "_baseURI": "http://app.example.com:8081", ... } }
Requests to the SamlFederationHandler must not be rebased, because the request URI must match the endpoint in the SAML metadata.
-
Add the following route to IG, to serve .css and other static resources for the sample application:
$HOME/.openig/config/routes/static-resources.json
appdata\OpenIG\config\routes\static-resources.json
{ "name" : "sampleapp-resources", "baseURI" : "http://app.example.com:8081", "condition": "${find(request.uri.path,'^/css')}", "handler": "ReverseProxyHandler" }
-
Add the following route to IG:
{ "name": "saml", "condition": "${find(request.uri.path, '^/saml')}", "session": "JwtSession", "handler": { "type": "SamlFederationHandler", "config": { "useOriginalUri": true, "assertionMapping": { "username": "cn", "password": "sn" }, "subjectMapping": "sp-subject-name", "redirectURI": "/home/federate" } } }
Notice the following features of the route:
-
The route matches requests to
/saml
. -
After authentication, the SamlFederationHandler extracts
cn
andsn
from the SAML assertion, and maps them to the SessionContext, atsession.username
andsession.password
. -
The handler stores the subject name as a string in the session field
session.sp-subject-name
, which is named by thesubjectMapping
property. By default, the subject name is stored in the session fieldsession.subjectName
. -
The handler redirects the request to the
/federate
route. -
The route uses the
JwtSession
implementation, meaning it stores encrypted session information in a browser cookie. The name is a reference to theJwtSession
object defined inconfig.json
. For information, see JwtSession.
-
-
Add the following route to IG:
{ "name": "federate", "condition": "${find(request.uri.path, '^/home/federate')}", "session": "JwtSession", "baseURI": "http://app.example.com:8081", "handler": { "type": "DispatchHandler", "config": { "bindings": [ { "condition": "${empty session.username}", "handler": { "type": "StaticResponseHandler", "config": { "status": 302, "headers": { "Location": [ "http://sp.example.com:8080/saml/SPInitiatedSSO?metaAlias=/sp" ] } } } }, { "handler": { "type": "Chain", "config": { "filters": [ { "type": "HeaderFilter", "config": { "messageType": "REQUEST", "add": { "x-username": ["${session.username[0]}"], "x-password": ["${session.password[0]}"] } } } ], "handler": "ReverseProxyHandler" } } } ] } } }
Notice the following features of the route:
-
The route matches requests to
/home/federate
. -
If the user is not authenticated with AM, the username is not populated in the context. The DispatchHandler then dispatches the request to the StaticResponseHandler, which redirects it to the SP-initiated SSO endpoint.
If the credentials are in the context, or after successful authentication, the DispatchHandler dispatches the request to the Chain.
-
The HeaderFilter adds headers for the first value for the
username
andpassword
attributes of the SAML assertion. -
The route uses the
JwtSession
implementation, meaning it stores encrypted session information in a browser cookie. The name is a reference to theJwtSession
object defined inconfig.json
. For information, see JwtSession.
-
-
Restart IG.
-
-
Test the setup:
-
Log out of AM, and test the setup with the following links:
-
Log in to AM with username
demo
and passwordCh4ng31t
.IG returns the response page showing that the the demo user has logged in.
-
For more control over the URL where the user agent is redirected, use the
The In the following example, the user is finally redirected to the original URI from the request:
|
Set up federation with signed/encrypted assertions
-
Set up the example in Set up federation with unsigned/unencrypted assertions.
-
Set up the SAML keystore:
-
Find the values of AM’s default SAML keypass and storepass:
$ more /path/to/am/security/secrets/default/.keypass $ more /path/to/am/security/secrets/default/.storepass
-
Copy the SAML keystore from the AM configuration to IG:
$ cp /path/to/am/security/keystores/keystore.jceks /path/to/ig/keystore.jceks
Legacy keystore types such as JKS and JCEKS are supported but are not secure. Consider using the PKCS#12 keystore type.
-
-
Configure the Fedlet in IG:
-
In
FederationConfig.properties
, make the following changes:-
Delete the following lines:
-
com.sun.identity.saml.xmlsig.keystore=%BASE_DIR%/security/keystores/keystore.jks
-
com.sun.identity.saml.xmlsig.storepass=%BASE_DIR%/.storepass
-
com.sun.identity.saml.xmlsig.keypass=%BASE_DIR%/.keypass
-
com.sun.identity.saml.xmlsig.certalias=test
-
com.sun.identity.saml.xmlsig.storetype=JKS
-
am.encryption.pwd=@AM_ENC_PWD@
-
-
Add the following line:
org.forgerock.openam.saml2.credential.resolver.class=org.forgerock.openig.handler.saml.SecretsSaml2CredentialResolver
This class is responsible for resolving secrets and supplying credentials.
Be sure to leave no space at the end of the line.
-
-
In
sp.xml
, make the following changes:-
Change
AuthnRequestsSigned="false"
toAuthnRequestsSigned="true"
. -
Add the following KeyDescriptor just before
</SPSSODescriptor>
<KeyDescriptor use="signing"> <ds:KeyInfo xmlns:ds="http://www.w3.org/2000/09/xmldsig#" > <ds:X509Data> <ds:X509Certificate> </ds:X509Certificate> </ds:X509Data> </ds:KeyInfo> </KeyDescriptor> </SPSSODescriptor>
-
Copy the value of the signing certificate from
idp.xml
to this file:<KeyDescriptor use="signing"> <ds:KeyInfo> <ds:X509Data> <ds:X509Certificate> MII...zA6 </ds:X509Certificate>
This is the public key used for signing so that the IDP can verify request signatures.
-
-
-
Replace the remote service provider in AM:
-
Select Applications > Federation > Entity Providers, and remove the
sp
entity provider. -
Drag in or import the new
sp.xml
updated in the previous step. -
Select Circles of Trust:
Circle of Trust
.
-
-
Set up IG:
-
In the IG configuration, set environment variables for the following secrets, and then restart IG:
$ export KEYSTORE_SECRET_ID='a2V5c3RvcmU=' $ export SAML_KEYSTORE_STOREPASS_SECRET_ID='<base64-encoded value of the SAML storepass>' $ export SAML_KEYSTORE_KEYPASS_SECRET_ID='<base64-encoded value of the SAML keypass>'
The passwords are retrieved by a SystemAndEnvSecretStore, and must be base64-encoded.
-
Remove
saml.json
from the configuration, and add the following route, replacing the path tokeystore.jceks
with your path:$HOME/.openig/config/routes/saml-secure.json
appdata\OpenIG\config\routes\saml-secure.json
{ "name": "saml-secure", "condition": "${find(request.uri.path, '^/saml')}", "session": "JwtSession", "heap": [ { "name": "SystemAndEnvSecretStore-1", "type": "SystemAndEnvSecretStore" }, { "name": "KeyStoreSecretStore-1", "type" : "KeyStoreSecretStore", "config" : { "file" : "/path/to/ig/keystore.jceks", "storeType" : "jceks", "storePasswordSecretId" : "saml.keystore.storepass.secret.id", "entryPasswordSecretId" : "saml.keystore.keypass.secret.id", "secretsProvider" : "SystemAndEnvSecretStore-1", "mappings" : [ { "secretId" : "sp.signing.sp", "aliases" : [ "rsajwtsigningkey" ] }, { "secretId" : "sp.decryption.sp", "aliases" : [ "test" ] } ] } } ], "handler": { "type": "SamlFederationHandler", "config": { "useOriginalUri": true, "assertionMapping": { "username": "cn", "password": "sn" }, "subjectMapping": "sp-subject-name", "redirectURI": "/home/federate", "secretsProvider" : "KeyStoreSecretStore-1" } } }
Notice the following features of the route compared to
saml.json
:-
The SamlFederationHandler refers to the KeyStoreSecretStore to provide the keys for the signed and encrypted SAML assertions.
-
The secret IDs,
sp.signing.sp
andsp.decryption.sp
, follow a naming convention based on the name of the service provider,sp
. -
The alias for the signing key corresponds to the PEM in
keystore.jceks
.
-
-
Restart IG.
-
-
Test the setup:
-
Log out of AM, and test the setup with the following links:
-
Log in to AM with username
demo
and passwordCh4ng31t
.IG returns the response page showing that the the demo user has logged in.
-
Use a non-transient NameID format
By default, AM as an IDP uses the NameID format
urn:oasis:names:tc:SAML:2.0:nameid-format:transient
.
For more information, refer to
Hosted identity provider configuration properties
in AM’s SAML v2.0 guide.
When the IDP uses another NameID format, configure IG to use
that NameID format by editing the Fedlet configuration file
sp-extended.xml
:
-
To use the NameID value provided by the IDP, add the following attribute:
<Attribute name="useNameIDAsSPUserID"> <Value>true</Value> </Attribute>
-
To use an attribute from the assertion, add the following attribute:
<Attribute name="autofedEnabled"> <Value>true</Value> </Attribute> <Attribute name="autofedAttribute"> <Value>sn</Value> </Attribute>
This example uses the value in
SN
to identify the subject.
Although IG supports the persistent
NameID format,
IG does not store the mapping. To configure this behavior, edit
the file sp-extended.xml
:
-
To disable attempts to persist the user mapping, add the following attribute:
<Attribute name="spDoNotWriteFederationInfo"> <Value>true</Value> </Attribute>
-
To enable attempts to persist the user mapping, add the following attribute:
<Attribute name="spDoNotWriteFederationInfo"> <Value>false</Value> </Attribute>
If a login request doesn’t contain a NameID format query parameter, the
value is defined by the presence and content of the NameID format list for
the SP and IDP. For example, an SP-initiated login can be constructed with
the binding and NameIDFormat
as a parameter, as follows:
http://fedlet.example.org:7070/fedlet/SPInitiatedSSO?binding=urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST&NameIDFormat=urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified
When the NameID format is provided in a list, it is resolved as follows:
-
If both the IDP and SP have a list, the first matching NameID format in the lists.
-
If either the IDP or SP list is empty, the first NameID format in the other list.
-
If neither the IDP nor SP has a list, then AM defaults to
transient
, and IG defaults topersistent
.
Example fedlet files
File | Description |
---|---|
|
Fedlet properties |
|
Circle of trust for IG and the IDP |
|
Standard metadata for the IDP |
|
Metadata extensions for the IDP |
|
Standard metadata for the IG SP |
|
Metadata extensions for the IG SP |
The following example of
$HOME/.openig/SAML/FederationConfig.properties
defines the fedlet
properties:
#
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
#
# Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved
#
# The contents of this file are subject to the terms
# of the Common Development and Distribution License
# (the License). You may not use this file except in
# compliance with the License.
#
# You can obtain a copy of the License at
# https://opensso.dev.java.net/public/CDDLv1.0.html or
# opensso/legal/CDDLv1.0.txt
# See the License for the specific language governing
# permission and limitations under the License.
#
# When distributing Covered Code, include this CDDL
# Header Notice in each file and include the License file
# at opensso/legal/CDDLv1.0.txt.
# If applicable, add the following below the CDDL Header,
# with the fields enclosed by brackets [] replaced by
# your own identifying information:
# "Portions Copyrighted [year] [name of copyright owner]"
#
# $Id: FederationConfig.properties,v 1.21 2010/01/08 22:41:28 exu Exp $
#
# Portions Copyright 2016-2023 ForgeRock AS.
# If a component wants to use a different datastore provider than the
# default one defined above, it can define a property like follows:
# com.sun.identity.plugin.datastore.class.<componentName>=<provider class>
# com.sun.identity.plugin.configuration.class specifies implementation for
# com.sun.identity.plugin.configuration.ConfigurationInstance interface.
com.sun.identity.plugin.configuration.class=com.sun.identity.plugin.configuration.impl.FedletConfigurationImpl
# Specifies implementation for
# com.sun.identity.plugin.datastore.DataStoreProvider interface.
# This property defines the default datastore provider.
com.sun.identity.plugin.datastore.class.default=com.sun.identity.plugin.datastore.impl.FedletDataStoreProvider
# Specifies implementation for
# org.forgerock.openam.federation.plugin.rooturl.RootUrlProvider interface.
# This property defines the default base url provider.
com.sun.identity.plugin.root.url.class.default=org.forgerock.openam.federation.plugin.rooturl.impl.FedletRootUrlProvider
# com.sun.identity.plugin.log.class specifies implementation for
# com.sun.identity.plugin.log.Logger interface.
com.sun.identity.plugin.log.class=com.sun.identity.plugin.log.impl.FedletLogger
# com.sun.identity.plugin.session.class specifies implementation for
# com.sun.identity.plugin.session.SessionProvider interface.
com.sun.identity.plugin.session.class=com.sun.identity.plugin.session.impl.FedletSessionProvider
# com.sun.identity.plugin.monitoring.agent.class specifies implementation for
# com.sun.identity.plugin.monitoring.FedMonAgent interface.
com.sun.identity.plugin.monitoring.agent.class=com.sun.identity.plugin.monitoring.impl.FedletAgentProvider
# com.sun.identity.plugin.monitoring.saml2.class specifies implementation for
# com.sun.identity.plugin.monitoring.FedMonSAML2Svc interface.
com.sun.identity.plugin.monitoring.saml2.class=com.sun.identity.plugin.monitoring.impl.FedletMonSAML2SvcProvider
# com.sun.identity.saml.xmlsig.keyprovider.class specified the implementation
# class for com.sun.identity.saml.xmlsig.KeyProvider interface
com.sun.identity.saml.xmlsig.keyprovider.class=com.sun.identity.saml.xmlsig.JKSKeyProvider
# com.sun.identity.saml.xmlsig.signatureprovider.class specified the
# implementation class for com.sun.identity.saml.xmlsig.SignatureProvider
# interface
com.sun.identity.saml.xmlsig.signatureprovider.class=com.sun.identity.saml.xmlsig.AMSignatureProvider
com.iplanet.am.server.protocol=http
com.iplanet.am.server.host=am.example.com
com.iplanet.am.server.port=8080
com.iplanet.am.services.deploymentDescriptor=/openam
com.iplanet.am.logstatus=ACTIVE
# Name of the webcontainer.
# Even though the servlet/JSP are web container independent,
# Access/Federation Manager uses servlet 2.3 API request.setCharacterEncoding()
# to decode incoming non English characters. These APIs will not work if
# Access/Federation Manager is deployed on Sun Java System Web Server 6.1.
# We use gx_charset mechanism to correctly decode incoming data in
# Sun Java System Web Server 6.1 and S1AS7.0. Possible values
# are BEA6.1, BEA 8.1, IBM5.1 or IAS7.0.
# If the web container is Sun Java System Webserver, the tag is not replaced.
com.sun.identity.webcontainer=WEB_CONTAINER
# Identify saml xml signature keystore file, keystore password file
# key password file
com.sun.identity.saml.xmlsig.keystore=%BASE_DIR%/security/keystores/keystore.jks
com.sun.identity.saml.xmlsig.storepass=%BASE_DIR%/.storepass
com.sun.identity.saml.xmlsig.keypass=%BASE_DIR%/.keypass
com.sun.identity.saml.xmlsig.certalias=test
# Type of keystore used for saml xml signature. Default is JKS.
#
# com.sun.identity.saml.xmlsig.storetype=JKS
# Specifies the implementation class for
# com.sun.identity.saml.xmlsig.PasswordDecoder interface.
com.sun.identity.saml.xmlsig.passwordDecoder=com.sun.identity.fedlet.FedletEncodeDecode
# The following key is used to specify the maximum content-length
# for an HttpRequest that will be accepted by the OpenSSO
# The default value is 16384 which is 16k
com.iplanet.services.comm.server.pllrequest.maxContentLength=16384
# The following keys are used to configure the Debug service.
# Possible values for the key 'level' are: off | error | warning | message.
# The key 'directory' specifies the output directory where the debug files
# will be created.
# Trailing spaces are significant.
# Windows: Use forward slashes "/" separate directories, not backslash "\".
# Windows: Spaces in the file name are allowed for Windows.
#
com.iplanet.services.debug.level=message
com.iplanet.services.debug.directory=%BASE_DIR%%SERVER_URI%/debug
# The following keys are used to configure the Stats service.
# Possible values for the key 'level' are: off | file | console
# Stats state 'file' will write to a file under the specified directory,
# and 'console' will write into webserver log files
# The key 'directory' specifies the output directory where the debug files
# will be created.
# Trailing spaces are significant.
# Windows: Use forward slashes "/" separate directories, not backslash "\".
# Windows: Spaces in the file name are allowed for Windows.
# Stats interval should be atleast 5 secs to avoid CPU saturation,
# the product would assume any thing less than 5 secs is 5 secs.
com.iplanet.am.stats.interval=60
com.iplanet.services.stats.state=file
com.iplanet.services.stats.directory=%BASE_DIR%/var/stats
# The key that will be used to encrypt and decrypt passwords.
am.encryption.pwd=@AM_ENC_PWD@
# SecureRandom Properties: The key
# "com.iplanet.security.SecureRandomFactoryImpl"
# specifies the factory class name for SecureRandomFactory
# Available impl classes are:
# com.iplanet.am.util.JSSSecureRandomFactoryImpl (uses JSS)
# com.iplanet.am.util.SecureRandomFactoryImpl (pure Java)
com.iplanet.security.SecureRandomFactoryImpl=com.iplanet.am.util.SecureRandomFactoryImpl
# SocketFactory properties: The key "com.iplanet.security.SSLSocketFactoryImpl"
# specifies the factory class name for LDAPSocketFactory
# Available classes are:
# com.iplanet.services.ldap.JSSSocketFactory (uses JSS)
# com.sun.identity.shared.ldap.factory.JSSESocketFactory (pure Java)
com.iplanet.security.SSLSocketFactoryImpl=com.sun.identity.shared.ldap.factory.JSSESocketFactory
# Encryption: The key "com.iplanet.security.encryptor" specifies
# the encrypting class implementation.
# Available classes are:
# com.iplanet.services.util.JCEEncryption
# com.iplanet.services.util.JSSEncryption
com.iplanet.security.encryptor=com.iplanet.services.util.JCEEncryption
# Determines if JSS will be added with highest priority to JCE
# Set this to "true" if other JCE providers should be used for
# digial signatures and encryptions.
com.sun.identity.jss.donotInstallAtHighestPriority=true
# Configuration File (serverconfig.xml) Location
com.iplanet.services.configpath=@BASE_DIR@
The following example of $HOME/.openig/SAML/fedlet.cot
defines a circle
of trust between AM as the IDP, and IG as the SP:
cot-name=Circle of Trust
sun-fm-cot-status=Active
sun-fm-trusted-providers=openam, sp
sun-fm-saml2-readerservice-url=
sun-fm-saml2-writerservice-url=
The following example of $HOME/.openig/SAML/idp.xml
defines a SAML
configuration file for the AM IDP, idp
:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<EntityDescriptor entityID="openam" xmlns="urn:oasis:names:tc:SAML:2.0:metadata" xmlns:query="urn:oasis:names:tc:SAML:metadata:ext:query" xmlns:mdattr="urn:oasis:names:tc:SAML:metadata:attribute" xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion" xmlns:xenc="http://www.w3.org/2001/04/xmlenc#" xmlns:xenc11="http://www.w3.org/2009/xmlenc11#" xmlns:alg="urn:oasis:names:tc:SAML:metadata:algsupport" xmlns:x509qry="urn:oasis:names:tc:SAML:metadata:X509:query" xmlns:ds="http://www.w3.org/2000/09/xmldsig#">
<IDPSSODescriptor protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<KeyDescriptor use="signing">
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
...
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
</KeyDescriptor>
<KeyDescriptor use="encryption">
<ds:KeyInfo>
<ds:X509Data>
<ds:X509Certificate>
...
</ds:X509Certificate>
</ds:X509Data>
</ds:KeyInfo>
<EncryptionMethod Algorithm="http://www.w3.org/2009/xmlenc11#rsa-oaep">
<ds:DigestMethod Algorithm="http://www.w3.org/2001/04/xmlenc#sha256"/>
<xenc11:MGF Algorithm="http://www.w3.org/2009/xmlenc11#mgf1sha256"/>
</EncryptionMethod>
<EncryptionMethod Algorithm="http://www.w3.org/2001/04/xmlenc#aes128-cbc">
<xenc:KeySize>128</xenc:KeySize>
</EncryptionMethod>
</KeyDescriptor>
<ArtifactResolutionService index="0" Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://am.example.com:8088/openam/ArtifactResolver/metaAlias/idp"/>
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://am.example.com:8088/openam/IDPSloRedirect/metaAlias/idp" ResponseLocation="http://am.example.com:8088/openam/IDPSloRedirect/metaAlias/idp"/>
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://am.example.com:8088/openam/IDPSloPOST/metaAlias/idp" ResponseLocation="http://am.example.com:8088/openam/IDPSloPOST/metaAlias/idp"/>
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://am.example.com:8088/openam/IDPSloSoap/metaAlias/idp"/>
<ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://am.example.com:8088/openam/IDPMniRedirect/metaAlias/idp" ResponseLocation="http://am.example.com:8088/openam/IDPMniRedirect/metaAlias/idp"/>
<ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://am.example.com:8088/openam/IDPMniPOST/metaAlias/idp" ResponseLocation="http://am.example.com:8088/openam/IDPMniPOST/metaAlias/idp"/>
<ManageNameIDService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://am.example.com:8088/openam/IDPMniSoap/metaAlias/idp"/>
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:persistent</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:unspecified</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:WindowsDomainQualifiedName</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:kerberos</NameIDFormat>
<NameIDFormat>urn:oasis:names:tc:SAML:1.1:nameid-format:X509SubjectName</NameIDFormat>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://am.example.com:8088/openam/SSORedirect/metaAlias/idp"/>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://am.example.com:8088/openam/SSOPOST/metaAlias/idp"/>
<SingleSignOnService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://am.example.com:8088/openam/SSOSoap/metaAlias/idp"/>
<NameIDMappingService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://am.example.com:8088/openam/NIMSoap/metaAlias/idp"/>
<AssertionIDRequestService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://am.example.com:8088/openam/AIDReqSoap/IDPRole/metaAlias/idp"/>
<AssertionIDRequestService Binding="urn:oasis:names:tc:SAML:2.0:bindings:URI" Location="http://am.example.com:8088/openam/AIDReqUri/IDPRole/metaAlias/idp"/>
</IDPSSODescriptor>
</EntityDescriptor>
The following example of $HOME/.openig/SAML/idp-extended.xml
defines an
AM-specific SAML descriptor file for the IDP:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!--
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright (c) 2002-2010 Sun Microsystems Inc. All Rights Reserved
The contents of this file are subject to the terms
of the Common Development and Distribution License
(the License). You may not use this file except in
compliance with the License.
You can obtain a copy of the License at
https://opensso.dev.java.net/public/CDDLv1.0.html or
opensso/legal/CDDLv1.0.txt
See the License for the specific language governing
permission and limitations under the License.
When distributing Covered Code, include this CDDL
Header Notice in each file and include the License file
at opensso/legal/CDDLv1.0.txt.
If applicable, add the following below the CDDL Header,
with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
Portions Copyrighted 2010-2017 ForgeRock AS.
-->
<EntityConfig entityID="openam" hosted="0" xmlns="urn:sun:fm:SAML:2.0:entityconfig">
<IDPSSOConfig>
<Attribute name="description">
<Value/>
</Attribute>
<Attribute name="cotlist">
<Value>Circle of Trust</Value>
</Attribute>
</IDPSSOConfig>
<AttributeAuthorityConfig>
<Attribute name="cotlist">
<Value>Circle of Trust</Value>
</Attribute>
</AttributeAuthorityConfig>
<XACMLPDPConfig>
<Attribute name="wantXACMLAuthzDecisionQuerySigned">
<Value></Value>
</Attribute>
<Attribute name="cotlist">
<Value>Circle of Trust</Value>
</Attribute>
</XACMLPDPConfig>
</EntityConfig>
The SAML library component validates the SP’s AssertionConsumerService
Location against the incoming IDP SAML Assertion, based on the request
information, including the port. Always specify the port in the Location
value of
|
The following example of $HOME/.openig/SAML/sp.xml
defines a SAML
configuration file for the IG SP, sp
.
<!--
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright (c) 2002-2010 Sun Microsystems Inc. All Rights Reserved
The contents of this file are subject to the terms
of the Common Development and Distribution License
(the License). You may not use this file except in
compliance with the License.
You can obtain a copy of the License at
https://opensso.dev.java.net/public/CDDLv1.0.html or
opensso/legal/CDDLv1.0.txt
See the License for the specific language governing
permission and limitations under the License.
When distributing Covered Code, include this CDDL
Header Notice in each file and include the License file
at opensso/legal/CDDLv1.0.txt.
If applicable, add the following below the CDDL Header,
with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
Portions Copyrighted 2010-2017 ForgeRock AS.
-->
<EntityDescriptor entityID="sp" xmlns="urn:oasis:names:tc:SAML:2.0:metadata">
<SPSSODescriptor AuthnRequestsSigned="false" WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Redirect" Location="http://sp.example.com:8080/saml/fedletSloRedirect" ResponseLocation="http://sp.example.com:8080/saml/fedletSloRedirect"/>
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://sp.example.com:8080/saml/fedletSloPOST" ResponseLocation="http://sp.example.com:8080/saml/fedletSloPOST"/>
<SingleLogoutService Binding="urn:oasis:names:tc:SAML:2.0:bindings:SOAP" Location="http://sp.example.com:8080/saml/fedletSloSoap"/>
<NameIDFormat>urn:oasis:names:tc:SAML:2.0:nameid-format:transient</NameIDFormat>
<AssertionConsumerService isDefault="true" index="0" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-POST" Location="http://sp.example.com:8080/saml/fedletapplication/metaAlias/sp"/>
<AssertionConsumerService index="1" Binding="urn:oasis:names:tc:SAML:2.0:bindings:HTTP-Artifact" Location="http://sp.example.com:8080/saml/fedletapplication/metaAlias/sp"/>
</SPSSODescriptor>
<RoleDescriptor xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:query="urn:oasis:names:tc:SAML:metadata:ext:query" xsi:type="query:AttributeQueryDescriptorType" protocolSupportEnumeration= "urn:oasis:names:tc:SAML:2.0:protocol">
</RoleDescriptor>
<XACMLAuthzDecisionQueryDescriptor WantAssertionsSigned="false" protocolSupportEnumeration="urn:oasis:names:tc:SAML:2.0:protocol">
</XACMLAuthzDecisionQueryDescriptor>
</EntityDescriptor>
The following example of $HOME/.openig/SAML/sp-extended.xml
defines an
AM-specific SAML descriptor file for the SP:
<!--
DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
Copyright (c) 2002-2010 Sun Microsystems Inc. All Rights Reserved
The contents of this file are subject to the terms
of the Common Development and Distribution License
(the License). You may not use this file except in
compliance with the License.
You can obtain a copy of the License at
https://opensso.dev.java.net/public/CDDLv1.0.html or
opensso/legal/CDDLv1.0.txt
See the License for the specific language governing
permission and limitations under the License.
When distributing Covered Code, include this CDDL
Header Notice in each file and include the License file
at opensso/legal/CDDLv1.0.txt.
If applicable, add the following below the CDDL Header,
with the fields enclosed by brackets [] replaced by
your own identifying information:
"Portions Copyrighted [year] [name of copyright owner]"
Portions Copyrighted 2010-2017 ForgeRock AS.
-->
<EntityConfig xmlns="urn:sun:fm:SAML:2.0:entityconfig" xmlns:fm="urn:sun:fm:SAML:2.0:entityconfig" hosted="1" entityID="sp">
<SPSSOConfig metaAlias="/sp">
<Attribute name="description">
<Value></Value>
</Attribute>
<Attribute name="signingCertAlias">
<Value></Value>
</Attribute>
<Attribute name="encryptionCertAlias">
<Value></Value>
</Attribute>
<Attribute name="basicAuthOn">
<Value>false</Value>
</Attribute>
<Attribute name="basicAuthUser">
<Value></Value>
</Attribute>
<Attribute name="basicAuthPassword">
<Value></Value>
</Attribute>
<Attribute name="autofedEnabled">
<Value>false</Value>
</Attribute>
<Attribute name="autofedAttribute">
<Value></Value>
</Attribute>
<Attribute name="transientUser">
<Value>anonymous</Value>
</Attribute>
<Attribute name="spAdapter">
<Value></Value>
</Attribute>
<Attribute name="spAdapterEnv">
<Value></Value>
</Attribute>
<Attribute name="fedletAdapter">
<Value></Value>
</Attribute>
<Attribute name="fedletAdapterEnv">
<Value></Value>
</Attribute>
<Attribute name="spAccountMapper">
<Value>com.sun.identity.saml2.plugins.DefaultLibrarySPAccountMapper</Value>
</Attribute>
<Attribute name="spAttributeMapper">
<Value>com.sun.identity.saml2.plugins.DefaultSPAttributeMapper</Value>
</Attribute>
<Attribute name="spAuthncontextMapper">
<Value>com.sun.identity.saml2.plugins.DefaultSPAuthnContextMapper</Value>
</Attribute>
<Attribute name="spAuthncontextClassrefMapping">
<Value>urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport|0|default</Value>
</Attribute>
<Attribute name="spAuthncontextComparisonType">
<Value>exact</Value>
</Attribute>
<Attribute name="attributeMap">
<Value>*=*</Value>
</Attribute>
<Attribute name="saml2AuthModuleName">
<Value></Value>
</Attribute>
<Attribute name="localAuthURL">
<Value></Value>
</Attribute>
<Attribute name="intermediateUrl">
<Value></Value>
</Attribute>
<Attribute name="defaultRelayState">
<Value></Value>
</Attribute>
<Attribute name="appLogoutUrl">
<Value>http://sp.example.com:8080/saml/logout</Value>
</Attribute>
<Attribute name="assertionTimeSkew">
<Value>300</Value>
</Attribute>
<Attribute name="wantAttributeEncrypted">
<Value></Value>
</Attribute>
<Attribute name="wantAssertionEncrypted">
<Value></Value>
</Attribute>
<Attribute name="wantNameIDEncrypted">
<Value></Value>
</Attribute>
<Attribute name="wantPOSTResponseSigned">
<Value></Value>
</Attribute>
<Attribute name="wantArtifactResponseSigned">
<Value></Value>
</Attribute>
<Attribute name="wantLogoutRequestSigned">
<Value></Value>
</Attribute>
<Attribute name="wantLogoutResponseSigned">
<Value></Value>
</Attribute>
<Attribute name="wantMNIRequestSigned">
<Value></Value>
</Attribute>
<Attribute name="wantMNIResponseSigned">
<Value></Value>
</Attribute>
<Attribute name="cotlist">
<Value>Circle of Trust</Value></Attribute>
<Attribute name="saeAppSecretList">
</Attribute>
<Attribute name="saeSPUrl">
<Value></Value>
</Attribute>
<Attribute name="saeSPLogoutUrl">
</Attribute>
<Attribute name="ECPRequestIDPListFinderImpl">
<Value>com.sun.identity.saml2.plugins.ECPIDPFinder</Value>
</Attribute>
<Attribute name="ECPRequestIDPList">
<Value></Value>
</Attribute>
<Attribute name="enableIDPProxy">
<Value>false</Value>
</Attribute>
<Attribute name="idpProxyList">
<Value></Value>
</Attribute>
<Attribute name="idpProxyCount">
<Value>0</Value>
</Attribute>
<Attribute name="useIntroductionForIDPProxy">
<Value>false</Value>
</Attribute>
</SPSSOConfig>
<AttributeQueryConfig metaAlias="/attrQuery">
<Attribute name="signingCertAlias">
<Value></Value>
</Attribute>
<Attribute name="encryptionCertAlias">
<Value></Value>
</Attribute>
<Attribute name="wantNameIDEncrypted">
<Value></Value>
</Attribute>
<Attribute name="cotlist">
<Value>Circle of Trust</Value>
</Attribute>
</AttributeQueryConfig>
<XACMLAuthzDecisionQueryConfig metaAlias="/pep">
<Attribute name="signingCertAlias">
<Value></Value>
</Attribute>
<Attribute name="encryptionCertAlias">
<Value></Value>
</Attribute>
<Attribute name="basicAuthOn">
<Value>false</Value>
</Attribute>
<Attribute name="basicAuthUser">
<Value></Value>
</Attribute>
<Attribute name="basicAuthPassword">
<Value></Value>
</Attribute>
<Attribute name="wantXACMLAuthzDecisionResponseSigned">
<Value></Value>
</Attribute>
<Attribute name="wantAssertionEncrypted">
<Value></Value>
</Attribute>
<Attribute name="cotlist">
<Value>Circle of Trust</Value>
</Attribute>
</XACMLAuthzDecisionQueryConfig>
</EntityConfig>
SAML 2.0 and multiple applications
The chapter extends the example in
SAML
with the service provider sp
, to add a second service provider.
The new service provider has entity ID sp2
and runs on the host
sp2.example.com
. To prevent unwanted behavior, the service providers must
have different values.
-
Add
sp2.example.com
to your/etc/hosts
file:127.0.0.1 localhost am.example.com ig.example.com app.example.com sp.example.com sp2.example.com
-
In IG, configure the service provider files for
sp2
, using the files you created in Configure a Java Fedlet::-
In
fedlet.cot
, addsp2
to the list of sun-fm-trusted-providers:cot-name=Circle of Trust sun-fm-cot-status=Active sun-fm-trusted-providers=openam, sp, sp2 sun-fm-saml2-readerservice-url= sun-fm-saml2-writerservice-url=
-
Copy
sp.xml
tosp2.xml
, and copysp-extended.xml
tosp2-extended.xml
. -
In both files, search and replace the following strings:
-
entityID=sp
: replace withentityID=sp2
-
sp.example.com
: replace withsp2.example.com
-
metaAlias=/sp
: replace withmetaAlias=/sp2
-
/metaAlias/sp
: replace with/metaAlias/sp2
-
-
Restart IG.
-
-
In AM, set up a remote service provider for
sp2
, as described in Set up federation with unsigned/unencrypted assertions:-
Select Applications > Federation > Entity Providers.
-
Drag in or import
sp2.xml
created in the previous step. -
Select Circles of Trust:
Circle of Trust
.
-
-
Add the following routes to IG:
{ "name": "saml-sp2", "condition": "${find(request.uri.host, 'sp2.example.com') and find(request.uri.path, '^/saml')}", "handler": { "type": "SamlFederationHandler", "config": { "comment": "Use unique session properties for this SP.", "useOriginalUri": true, "assertionMapping": { "sp2Username": "cn", "sp2Password": "sn" }, "authnContext": "sp2AuthnContext", "sessionIndexMapping": "sp2SessionIndex", "subjectMapping": "sp2SubjectName", "redirectURI": "/sp2" } } }
$HOME/.openig/config/routes/federate-sp2.json
appdata\OpenIG\config\routes\federate-sp2.json
{ "name": "federate-sp2", "condition": "${find(request.uri.host, 'sp2.example.com') and not find(request.uri.path, '^/saml')}", "baseURI": "http://app.example.com:8081", "handler": { "type": "DispatchHandler", "config": { "bindings": [ { "condition": "${empty session.sp2Username}", "handler": { "type": "StaticResponseHandler", "config": { "status": 302, "headers": { "Location": [ "http://sp2.example.com:8080/saml/SPInitiatedSSO?metaAlias=/sp2" ] } } } }, { "handler": { "type": "Chain", "config": { "filters": [ { "type": "HeaderFilter", "config": { "messageType": "REQUEST", "add": { "x-username": ["${session.sp2Username[0]}"], "x-password": ["${session.sp2Password[0]}"] } } } ], "handler": "ReverseProxyHandler" } } } ] } } }
-
Test the setup:
-
Log out of AM, and test the setup with the following links:
-
Log in to AM with username
demo
and passwordCh4ng31t
.IG returns the response page showing that the user has logged in.
-