SAML token library APIs
The SAML token library APIs provide methods we can use to create, validate, parse, and extract SAML tokens.
The library implementation for SAML Version 1.1 and SAML Version 2.0 provides three types of subject confirmation: holder-of-key (HoK), bearer, and sender-vouches. We can use the SAML token library APIs to create, validate, and extract the attributes of a SAML HoK or bearer token. SAML token propagation from web services SOAP messages is also discussed. Sample code is provided to demonstrate the use of the APIs.
WebSphere Application Server with SAML provides default policy sets to support the bearer and HoK subject confirmation.
The SAMLTokenFactory API is the primary SAML token library programming interface, supporting SAML 1.1 and SAML 2.0 tokens. We can create ProviderConfid, RequesterConfig, and ConsumerConfig configuration objects to define the required SAML token characteristics.
Starting with WebSphere Application Server Release 8, we can use the com.ibm.websphere.wssecurity.wssapi.token.SAMLToken class in Web Services Security (WSS) API. When there is no concern of confusion we use the term SAMLToken instead of using its complete package name. We can use WSS API to request SAMLToken processing from an external Security Token Service (STS), to propagate SAMLTokens in SOAP request messages, and to use a symmetric or asymmetric key identified by SAMLTokens to protect SOAP messages.
The WSS API SAML support complements the interfaces...
- com.ibm.websphere.wssecurity.wssapi.token.SAMLTokenFactory
- com.ibm.websphere.wssecurity.wssapi.trust.WSSTrustClient
SAMLTokens generated using com.ibm.websphere.wssecurity.wssapi.WSSFactory newSecurityToken() can be processed by the SAMLTokenFactory and WSSTrustClient programming interfaces. Conversely, SAMLTokens generated by SAMLTokenFactory or returned by WSSTrustClient can be used in WSS API. Deciding which API to use in the application depends on the specific needs. WSS API SAML support is self contained in the sense that it provides functionality equivalent to that of the SAMLTokenFactory and WSSTrustClient interfaces as far as web services client applications are concerned. The SAMLTokenFactory interface has additional functions to validate SAMLTokens and to create the JAAS Subject that represents authenticated SAMLTokens. This validation is useful for the Web services provider side. When you develop applications to consume SAMLTokens, the SAMLTokenFactory programming interface is more suitable for you.
Configuration of token creation parameters
When you configure the token creation parameters, the configuration information relates to either the requesting entity, the issuing entity, or the receiving entity. In this example, configuration information is defined for the requesting and the issuing entities. For each type of supported subject confirmation, the SAML token library provides pre-configured attributes for the requesting entity. These attributes are used during the creation of the self-issued SAML token by the WebSphere runtime environment. A self-issued SAML token is one that is generated locally, instead of one that is requested from a Security Token Service (STS). If we need to customize the attributes for a default parameter, use the RequesterConfig parameter. For more information, read about the RequesterConfig parameter in the SAMLTokenFactory API topic.
First, set up the requestor configuration information:
// Setup the requester's configuration information (parameters needed // to create the token specified as configuration properties). // in this case we are using the configuration information to create a // SAML token containing a symmetric holder of key subject // confirmation. RequesterConfig requesterData = samlFactory.newSymmetricHolderOfKeyTokenGenerateConfig();Next, set the recipient public key alias and optionally, the authentication method:
// Set recipient's public key alias // (in this example we use SOAPRecipient), so the provider can encrypt secret // key for the receiving end. requesterData.setKeyAliasForAppliesTo("SOAPRecipient"); // Set the authentication method that took place. This is an optional // parameter. reqData.setAuthenticationMethod("Password");Then set the issuer configuration attributes:
// Set issuer information by instantiating a default ProviderConfig. // See javadocs for the SAMLTokenFactory class on the details of the // default values and how to modify them. ProviderConfig samlIssuerCfg = samlFactory.newDefaultProviderConfig("WebSphereSelfIssuer");
SAML token factory instance creation
Use the SAMLTokenFactory class, specifying the SAML token type, either Version 1.1 or Version 2.0. Set additional parameters for creating the SAML token.Use the SAMLTokenFactory class with the SAML token type:
// Instantiate a token factory based on the version level of the token // to use. In this example we use the SAML v1.1 token factory. SAMLTokenFactory samlFactory = SAMLTokenFactory.getInstance(SAMLTokenFactory.WssSamlV11Token11);Set additional parameters in the CredentialConfig object using the caller subject or the runAsSubject:
// Retrieve the caller subject or the runAsSubject (depending on the // scenario) use the Subject to get a CredentialConfig object // using the SAML token library. // This invocation requires the // wssapi.SAMLTokenFactory.newCredentialConfig" Java Security // permission. CredentialConfig cred = samlFactory.newCredentialConfig(runAsSubject);
SAML token creation
Create the SAML token using the token factory:
// Now create the SAML token. This invocation requires the // "wssapi.SAMLTokenFactory.newSAMLToken" Java Security permission. SecurityToken samlToken = samlFactory.newSAMLToken(cred, reqData, samlIssuerCfg);
SAML token validation
An entity that receives a SAML token, such as a business service, can use the SAML token library API to validate the token before using it. For example, the service needs to validate the token before extracting the SAML attributes from the requester. An existing SAML assertion document can be validated using the configuration data from the consumer.
The following API code validates the token:
ConsumerConfig consumerConfig = samlFactory.newConsumerConfig(); XMLStructure xml = try { SAMLToken token = samlFactory.newSAMLToken( consumerConfig, XMLStructure xml ); // token successfully validated } catch(WSSException e){ // token failed validation }
SAML token identity mapped to a subject
A SAML token can be used to create a subject. The name identifier in the SAML token is mapped to a user in the user registry to obtain the principal name for the subject.Subject subject; SAMLToken aSAMLToken = ; try { subject = samlFactory.newSubject(aSAMLToken); } catch(WSSException e) { }
Parse assertion elements
The recipient of a SAML token can parse and extract assertion elements from the SAML token using the SAMLToken APIs, which are included in the SAML token library API. For example, the token creation time can be extracted using this code:Date dateCreated = samlToken.getSamlCreated();
Extract the name of the token issuer and the confirmation method as follows:
String confirmationMethpo = samlToken.getConfirmationMethod(); String issuerName = samlToken.getSAMLIssuerName();If the extracted subject confirmation method is returned as holder-of-key confirmation, then we can use the following API to retrieve the bytes for the key material:
byte[] hokBytes = samlToken.getHolderOfKeyBytes();
For more information about all the SAML APIs, read the API documentation for the SAMLToken interface.
SAML token attributes extraction
Extract SAML attributes from the initiating entity (service requester) using the SAMLToken API, as shown in the following code snippets.
// Get all attributes List<SAMLAttribute> allAttributes = ((SAMLToken) samlToken).getSAMLAttributes(); // Iterate over the attribute and process accordingly Iterator<SAMLAttribute> iter = allAttributes.iterator(); while (iter.hasNext()) { SAMLAttribute anAttribute = iter.next(); // Handle attributes String attributeName = anAttribute.getName(); String[] attributeValues = anAttribute.getStringAttributeValue(); }
Sample code
The sample code demonstrates how to use the SAML token library APIs to accomplish some of the operations previously described. A JVM property that points to the location of the SAML properties file is a prerequisite for running this code. The SAML properties file, SAMLIssuerConfig.properties, must contain configuration attributes related to the issuer (provider) of the SAML token.The default location of the SAMLIssuerConfig.properties file for the cell level is: app_server_root/profiles/$PROFILE/config/cells/$CELLNAME/sts.
For the server level, the default location is: app_server_root/profiles/$PROFILE/config/cells/$CELLNAME/nodes/$NODENAME/servers/$SERVERNAME.
IssuerURI=WebSphere TimeToLive=3600000 KeyStorePath=c:/samlsample/saml-provider.jceks KeyStoreType=jceks KeyStorePassword=myissuerstorepass KeyAlias=samlissuer KeyName=CN=SAMLIssuer, O=IBM, C=US KeyPassword=xxxxxxxxx TrustStorePath=c:/samlsample/saml-provider.jceks TrustStoreType=jceks TrustStorePassword=yyyyyyyy package samlsample; import java.util.List; import java.util.Iterator; import java.util.ArrayList; import javax.security.auth.Subject; // Import methods from the SAML token library import com.ibm.wsspi.wssecurity.saml.data.SAMLAttribute; import com.ibm.websphere.wssecurity.wssapi.token.SAMLToken; import com.ibm.wsspi.wssecurity.saml.config.ProviderConfig; import com.ibm.wsspi.wssecurity.saml.config.RequesterConfig; import com.ibm.wsspi.wssecurity.saml.config.CredentialConfig; import com.ibm.websphere.wssecurity.wssapi.token.SAMLTokenFactory; import com.ibm.websphere.wssecurity.wssapi.token.SecurityToken; import com.ibm.wsspi.wssecurity.core.token.config.RequesterConfiguration; public class SamlAPIsample { public void testSAMLTokenLibrary() throws Exception { try { // Get an instance of the SAML v1.1 token factory SAMLTokenFactory samlFactory = SAMLTokenFac tory.getInstance(SAMLTokenFactory.WssSamlV11Token11); // Generate default requester data for a subject confirmation of // type holder-of-key (secret key). RequesterConfig requesterData = samlFactory.newSymmetricHolderOfKeyTokenGenerateConfig(); // Set the recipient's key alias, so that the issuer can encrypt // the secret key for recipient as part of the subject confirmation. requesterData.setKeyAliasForAppliesTo("SOAPRecipient"); // Set the authentication method that took place. requesterData.setAuthenticationMethod("Password"); System.out.println("default holder of key confirmation key type is: "+ Requester Data.getRSTTProperties().get(RequesterConfiguration.RSTT.KEYTYPE)); Requester Data.getRSTTProperties().put(RequesterConfiguration.RSTT.KEYTYPE, "http://docs.oasis-open.org/ws-sx/ws-trust/200512/SymmetricKey"); requesterData.getRSTTProperties().put( RequesterConfiguration.RSTT.APPLIESTO_ADDRESS, "http://localhost:9080"); requesterData.setConfirmationMethod("holder-of-key"); // Set the recipient's key alias so that token infomation such as // the secret HoK can be encrypted by the issuer and decrypted by the // recipient. requesterData.setKeyAliasForAppliesTo("SOAPRecipient"); requesterData.setAuthenticationMethod("Password"); requesterData.getRSTTProperties().put( RequesterConfiguration.RSTT.ENCRYPTIONALGORITHM, "http://www.w3.org/2001/04/xmlenc#aes128-cbc"); requester Data.getRSTTProperties().put(RequesterConfiguration.RSTT.TOKENTYPE,"http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile- 1.1#SAMLV1.1"); requesterData.setRequesterIPAddress("9.53.52.65"); // Print requester configuration items System.out.println("authentication method for requester is: "+ requesterData.getAuthenticationMethod()); System.out.println("confirmation method for requester is: "+ requesterData.getConfirmationMethod()); System.out.println("key alias for requester is: "+ requesterData.getKeyAliasForRequester()); System.out.println("key alias for recipient as set in requester config is "+ requesterData.getKeyAliasForAppliesTo()); System.out.println("holder of key confirmation key type is: "+ Requester Data.getRSTTProperties().get(RequesterConfiguration.RSTT.KEYTYPE)); // Get an instance of the Credential config object CredentialConfig cred = samlFactory.newCredentialConfig(); cred.setRequesterNameID("Alice"); // Set some user attributes ArrayList<SAMLAttribute> userAttrs = new ArrayList<SAMLAttribute>(); SAMLAttribute anAttribute = new SAMLAttribute("EmployeeInfo", new String[] {"GreenRoofing","JohnDoe", "19XY981245"}, null, "WebSphere Namespace", null, "JohnDoeInfo " ); userAttrs.add(anAttribute); cred.setSAMLAttributes(userAttrs); // Get default provider configuration ProviderConfig samlIssuerCfg = samlFactory.newDefaultProviderConfig("WebSphereSelfIssuer"); System.out.println("time to live from the default provider config: "+ samlIssuerCfg.getTimeToLive()); System.out.println("keyStore path from default provider config: "+ samlIssuerCfg.getKeyStoreConfig().getPath()); System.out.println("keyStore type from default provider config: "+ samlIssuerCfg.getKeyStoreConfig().getType()); System.out.println("key alias from default provider config: "+ samlIssuerCfg.getKeyInformationConfig().getAlias()); // Generate the SAML token SecurityToken samlToken = samlFactory.newSAMLToken(cred, requesterData, samlIssuerCfg); System.out.println("token's creation Date is: "+((SAMLToken)samlToken).getSamlCreated().toString()); System.out.println("token's expiration Date is: "+((SAMLToken)samlToken).getSamlExpires().toString()); System.out.println("token's subject confirmation method is: "+((SAMLToken)samlToken).getConfirmationMethod()); // Create a Subject, mapping the name identifier in the token to a user // in the user registry to obtain the Principal name Subject subject = samlFactory.newSubject((SAMLToken)samlToken); // Retrieve attributes from the token List<SAMLAttribute> allAttributes = ((SAMLToken)samlToken).getSAMLAttributes(); // Iterate through the attributes and process accordingly Iterator<SAMLAttribute> iter = allAttributes.iterator(); while (iter.hasNext()) { SAMLAttribute attribute = iter.next(); String attributeName = attribute.getName(); String[] attributeValues = attribute.getStringAttributeValue(); System.out.println("attribute name = "+ attributeName + " attribute value = ["+ attributeValues[0]+ ", "+attributeValues[1]+ ", "+ attributeValues[2]+"]"); } } catch(Exception e) { e.printStackTrace(); } } }
Sample code output
default holder of key confirmation key type is: http://docs.oasis-open.org/ws-sx/ws-trust/200512/SymmetricKey authentication method for requester is: Password confirmation method for requester is: holder-of-key key alias for requester is: null key alias for recipient as set in requester config is SOAPRecipient holder of key confirmation key type is: http://docs.oasis-open.org/ws-sx/ws-trust/200512/SymmetricKey time to live from the default provider config: 3600000 keyStore path from default provider config: C:/saml/samlsample/saml-provider.jceks keyStore type from default provider config: jceks key alias from default provider config: samlissuer token's creation Date is: Mon Sep 14 15:49:00 CDT 2009 token's expiration Date is: Mon Sep 14 16:49:00 CDT 2009 token's subject confirmation method is: urn:oasis:names:tc:SAML:1.0:cm:holder-of-key attribute name = EmployeeInfo attribute value = [GreenRoofing, JohnDoe, 19XY981245]
API documentation - Application programming interfaces (package: com.ibm.websphere.wssecurity.wssapi.token)