Create a SAML holder-of-key token using the API
The SAML holder-of-key token extends the security token public interface in WebSphere Application Server, and can be used as a protection token. WebSphere Application Server provides a SAML library API for SAML holder-of-key token creation.
SAML token creation requires three parameters:
- com.ibm.wsspi.wssecurity.saml.config.RequesterConfig
- com.ibm.wsspi.wssecurity.saml.config.ProviderConfig
- com.ibm.wsspi.wssecurity.saml.config.CredentialConfig
Follow the steps to create an instance for each of the parameters and then create a SAML holder-of-key token. Alternatively to CredentialConfig, we can also use javax.security.auth.Subject. For more information, read the API documentation.
- Create a com.ibm.websphere.wssecurity.wssapi.token.SAMLTokenFactory instance using the SAML token version as a parameter. The supported SAMLToken versions are http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV1.1 and http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0. The SAMLTokenFactory instance is a singleton and therefore is thread-safe. Using one of these lines of code to create the instance, depending on the token version.
- Use the following line of code to create a com.ibm.websphere.wssecurity.wssapi.token.SAMLTokenFactory instance for a version 1.1 SAML token:
SAMLTokenFactory samlFactory = SAMLTokenFactory.getInstance(SAMLTokenFactory.WssSamlV11Token11);
- Use the following line of code to create a com.ibm.websphere.wssecurity.wssapi.token.SAMLTokenFactory instance for a version 2.0 SAML token:
SAMLTokenFactory samlFactory = SAMLTokenFactory.getInstance(SAMLTokenFactory.WssSamlV11Token20);
- The SAMLTokenFactory instance is used to create a RequesterConfig instance, which determines how the token is generated, according the authentication requirements of the requester. Using one of these lines of code to create the RequesterConfig instance, depending on whether you want the token to use a secret key (symmetric key) or a public key:
- Use the following line of code to create a default RequesterConfig for the SAML holder-of-key token using a secret key (symmetric key), which is included in the SubjectConfirmation:
RequesterConfig reqData = samlFactory. newSymmetricHolderOfKeyTokenGenerateConfig ();
We must also set the key alias for the target service so the provider can encrypt the secret key for the service:
reqData.setKeyAliasForAppliesTo("SoapRecipient");
- Use the following line of code to create a default RequesterConfig for the SAML holder-of-key token using a public key, which is included in the SubjectConfirmation:
RequesterConfig reqData = samlFactory. newAsymmetricHolderOfKeyTokenGenerateConfig ();
We must also set the key alias for the requester so the provider can extract the public key from the requester, and include the key in the SubjectConfirmation:
reqData.setKeyAliasForRequester(SOAP Initiator);
The default RequestConfig instance is sufficient to generate a simple holder-of-key token, but additional assertions can be included in the SAML token by customizing the RequesterConfig instance. For example, to include password authentication information in the token, use setAuthenticationMethod:
reqData.setAuthenticationMethod(password);
- Use the SAMLTokenFactory to create a ProviderConfig instance, which describes the token issuer. The ProviderConfig instance specifies the SAML issuer name, as well as keystore and truststore information, which identifies the key for SAML encryption and signing. The ProviderConfig instance is created using property values from a property file. The property file specifies the default value of the ProviderConfig object. In a Java client environment, this property file is defined by a JVM system property, com.ibm.webservices.wssecurity.platform.SAMLIssuerConfigDataPath.
In the WAS runtime environment, the property file name is SAMLIssuerConfig.properties. The file can be located either under the server level configuration directory, or the cell level directory, in that order of precedence. An example of the server level path follows:
app_server_root/profiles/$PROFILE/config/cells/$CELLNAME/nodes/$NODENAME/servers/$SERVERNAME/SAMLIssuerConfig.properties
An example of the cell level path follows:
app_server_root/profiles/$PROFILE/config/cells/$CELLNAME/sts/SAMLIssuerConfig.properties
The JVM system property, com.ibm.webservices.wssecurity.platform.SAMLIssuerConfigDataPath, is ignored if the property is defined in server runtime environment. For a detailed description of all the properties, read about configuration of a SAML token during token creation.
Use the following line of code to create a default ProviderConfig instance:
ProviderConfig samlIssuerCfg = samlFactory.newDefaultProviderConfig(any issuer name);
The issuer name is optional. If the issuer name is specified, the Issuer name appears in the SAML assertion. If the issuer name is not specified, a default issuer name property from the SAMLIssuerConfig.properties is used as the issuer name.
- Optional: When creating a new SAML token, the SAMLTokenFactory uses either a JAAS subject or a CredentialConfig instance to populate the new SAML token. To use a JAAS subject to populate the token, use the com.ibm.websphere.security.auth.WSSubject getCallerSubject() API or the getRunAsSubject() API to obtain a JAAS subject that represents the requesting client, or the identity of the execution thread.
When we use the JAAS subject to create a new SAML token, the SAMLTokenFactory searches for a SAMLToken object in the subject PrivateCredentials list. If a SAMLToken object exists, the NameId or NameIdentifier are copied to the new SAML token. The SAMLTokenFactory also copies the SAML attributes and AuthenticationMethod from the existing SAML token to the new SAML token. The new SAML token includes a new issuer name, new signing certificate, confirmation method, new KeyInfo for the holder-of-key confirmation method, and new NotBefore and NotOnAfter conditions. These token settings are determined by the configuration parameters in the ProviderConfig and RequesterConfig objects.
If there is no SAMLToken object in the subject, only the WSPrincipal principal name is copied from the subject to the new SAML token. No other attributes in the subject are copied into the new SAML token. Similarly, the issuer name, signing certificate, confirmation method, KeyInfo for the holder-of-key, and NotBefore and NotOnOrAfter conditions are determined by configuration parameters in ProviderConfig and RequesterConfig objects.
Alternately, we can use the RunAsSubject method on the execution thread to create the SAML token. When using this method, do not pass the JAAS subject or the CredentialConfig object to the SAMLTokenFactory to create the SAML token. Instead, the content of the existing SAML token is copied to the new SAML token, as described previously.
Another method of creating a SAML token is to use a CredentialConfig object to populate the SAML NameId and Attributes programmatically. Use this method in the following circumstances:
- Custom SAML attributes must be included in the new SAML token.
- The SAML token is created manually instead of using the SAMLTokenFactory to populate the SAML token from a JAAS subject automatically.
- There is no existing SAML token in the subject.
- There is no JAAS subject available.
To create a CredentialConfig object without using the JAAS subject, use this line of code:
CredentialConfig cred = samlFactory.newCredentialConfig ();
There is no initial value provided for this CredentialConfig object, so use setter methods to populate the CredentialConfig object.
To populate the SAML NameIdentifier or NameID, use the following line of code:
cred.setRequesterNameID("any name");
The value of the any name variable is used as the principal name in the SAML token. The name appears in the assertion as the NameIdentifier in a SAML Version 1.1 token, or NameId in the SAML Version 2.0 token. For example, if the value of any name is Alice, the following assertion is generated in a SAML Version 1.1 token:
<saml:NameIdentifier>Alice</saml:NameIdentifier>
The following assertion is generated in a SAML Version 2.0 token:
<saml2:NameID>Alice</saml2:NameID>
To include SAML attributes in the <AttributeStatement> portion of an assertion, use this code:
SAMLAttribute samlAttribute = new SAMLAttribute("email" /* Name*/, new String[] {"joe@websphere"} /*Attribute Values*/, null, "IBM WebSphere namespace" /* namespace*/, "email" /* format*/, "joe" /*friendly name */); ArrayList<SAMLAttribute> al = new ArrayList<SAMLAttribute>(); al.add(samlAttribute) sattribute = new SAMLAttribute("Membership", new String[] {"Super users", "Gold membership"}, null, null /* format*/, null, null ); al.add(samlAttribute ); cred.setSAMLAttributes(al);This sample code generates the following <Attribute> assertions:
<saml:Attribute AttributeName="email" NameFormat="email" AttributeNamespace="IBM WebSphere namespace"> <saml:AttributeValue>joe@websphere</saml:AttributeValue> </saml:Attribute> <saml:Attribute AttributeName="Membership"> <saml:AttributeValue>Super users</saml:AttributeValue><saml:AttributeValue>Gold membership</saml:AttributeValue> </saml:Attribute>
- Generate a SAML holder-of-key token using this line of code:
SAMLToken samlToken = samlFactory.newSAMLToken(cred, reqData, samlIssuerCfg);
This method requires the Java security permission wssapi.SAMLTokenFactory.newSAMLToken. Complete code samples using lines of code from the previous steps are included in the Example section.
Example
Use this sample code to create a SAML version 1.1 holder-of-key token using a secret key (symmetric key) from the subject.
import com.ibm.wsspi.wssecurity.saml.config.RequesterConfig; import com.ibm.wsspi.wssecurity.saml.config.ProviderConfig; import com.ibm.wsspi.wssecurity.saml.config.CredentialConfoig ; import com.ibm.websphere.wssecurity.wssapi.token.SAMLTokenFactory SAMLTokenFactory samlFactory = SAMLTokenFactory.getInstance(SAMLTokenFactory.WssSamlV11Token11); RequesterConfig reqData = samlFactory.newSymmetricHolderOfKeyTokenGenerateConfig(); //Map "AppliesTo" to key alias, so library knows how to encrypt the Symmetric Key reqData.setKeyAliasForAppliesTo("SOAPRecipient"); ProviderConfig samlIssuerCfg = samlFactory.newDefaultProviderConfig(IsserUri); Subject subject = com.ibm.websphere.security.auth.WSSubject.getRunAsSubject(); SAMLToken samlToken = samlFactory.newSAMLToken(subject, reqData, samlIssuerCfg);Use this sample code to create a SAML version 2.0 holder-of-key token using a public key from the subject:
//User expression on how SAML should be created, default provided RequesterConfig reqData = samlFactory.newAsymmetricHolderOfKeyTokenGenerateConfig(); //Choose a public key to be included in SAML reqData.setKeyAliasForRequester("SOAPInitiator"); //Get issuer key store so can sign or encrypt assertion, issuer name ProviderConfig samlIssuerCfg = samlFactory.newDefaultProviderConfig("any_issuer"); //Get JAAS Subject so the factory can populate principal and attributes to SAML Subject subject = com.ibm.websphere.security.auth.WSSubject.getRunAsSubject(); SAMLToken samlToken = samlFactory.newSAMLToken(subject, reqData, samlIssuerCfg);Use this sample code to create a SAML version 2.0 holder-of-key token using a secret key (symmetric key):
SAMLTokenFactory samlFactory = SAMLTokenFactory.getInstance (SAMLTokenFactory.WssSamlV20Token11); RequesterConfig reqData = samlFactory. newSymmetricHolderOfKeyTokenGenerateConfig (); //Map "AppliesTo" to key alias so library knows how to encrypt the Symmetric Key reqData.setKeyAliasForAppliesTo("SOAPRecipient"); ProviderConfig samlIssuerCfg = samlFactory.newDefaultProviderConfig(null); CredentialConfig cred = samlFactory.newCredentialConfig (); cred.setRequesterNameID("any_name"); SAMLToken samlToken = samlFactory.newSAMLToken(subject, reqData, samlIssuerCfg);
Related concepts
SAML assertions defined in the SAML Token Profile standard
Related tasks
Configure client and provider bindings for the SAML holder-of-key symmetric key token