You can create self-issued SAML tokens with the bearer subject confirmation method and
then send these tokens with Web services request messages using the Java™ API for XML-Based Web Services (JAX-WS) programming model and Web Services Security APIs
(WSS API).
Before you begin
This task assumes that you are familiar with the JAX-WS programming model, the WSS API
interfaces, SAML concepts, and the use of policy sets to configure and administer web services
settings.
About this task
You can build your web services client to use SAML tokens with the bearer subject confirmation
method in SOAP request messages using the Web Services Security programming interfaces. Using the
programming interfaces in a web services client to specify the use of SAML tokens with bearer
subject confirmation is an alternative approach to using policy sets and binding configurations.
You can create a self-issued SAML token and then send the SAML token in web services request
messages from a web services client. The web services application client used in this task is a
modified version of the client code that is contained in the JaxWSServicesSamples sample application that is available for download. Code
snippets from the sample are described in the procedure section, and a complete, ready-to-use web
services client sample is provided in the Example section.
Procedure
-
Identify and obtain the web services client that you want to use to invoke a web services
provider.
Use this client to insert SAML tokens in SOAP request messages programmatically using WSS APIs.
The web services client used in this procedure is a modified version of the client code that is
contained in the JaxWSServicesSamples web services sample application.
To obtain and modify the sample web services client to add the Web Services Security API to pass
SAML tokens in SOAP request messages programmatically using WSS APIs, complete the following
steps:
-
Download the JaxWSServicesSamples sample application.
The JaxWSServicesSamples sample is not installed by default.
-
Obtain the JaxWSServicesSamples client code.
For example purposes, this procedure uses a modified version of the Echo thin client sample that
is included in the JaxWSServicesSamples sample. The web services Echo thin client sample file,
SampleClient.java, is located in the
src\SampleClientSei\src\com\ibm\was\wssample\sei\cli directory. The sample
class file is included in the WSSampleClientSei.jar file.
The JaxWSServicesSamples.ear enterprise application and supporting Java archives (JAR) files are located in the
installableApps directory within the JaxWSServicesSamples sample
application.
-
Deploy the JaxWSServicesSamples.ear file onto the application
server.
After you deploy the JaxWSServicesSamples.ear file, you are ready to test
the sample web services client code against the sample application.
Instead of using the web services client sample, you can choose to add the code snippets to pass
SAML tokens in SOAP request messages programmatically using WSS APIs in your own web services client
application. The example in this procedure uses a JAX-WS Web services thin client; however, you can
also use a managed client.
-
Attach the SAML20 Bearer WSHTTPS default policy set to the web services provider.
This policy set is used to protect messages using HTTPS transport. Read about configuring
client and provider bindings for the SAML Bearer token for details on how to attach the SAML20
Bearer WSHTTPS default policy set to the Web services provider. The example in this procedure uses
self-issued SAML tokens. When you configure the provider bindings, the truststore configuration and
certificate must match the signing key of the self-issued token.
-
Assign the SAML Bearer Provider sample default general bindings to the sample web services
provider.
Read about configuring client and provider bindings for the SAML bearer token for details on
assigning the SAML Bearer Provider sample default general bindings to your web services application.
-
Create the self-issued SAML token.
The following code snippet illustrates creating the SAML
token:
// Create the SAML token.
HashMap<Object, Object> map = new HashMap<Object, Object>();
map.put(SamlConstants.CONFIRMATION_METHOD, "Bearer");
map.put(SamlConstants.TOKEN_TYPE, WSSConstants.SAML.SAML20_VALUE_TYPE);
map.put(SamlConstants.SAML_NAME_IDENTIFIER, "Alice");
map.put(SamlConstants.SIGNATURE_REQUIRED, "true");
SAMLGenerateCallbackHandler callbackHandler = new SAMLGenerateCallbackHandler(map);
callbackHandler.setWSSGenerationContextForTrustClient(gencont);
SecurityToken samlToken = factory.newSecurityToken(SAMLToken.class, callbackHandler, "system.wss.generate.saml");
System.out.println("SAMLToken id = " + samlToken.getId());
-
Use the CallService() method to specify the Web services security configuration parameters that
are required to invoke a target Web services provider using a self-issued SAML token.
The CallService() method sets the configuration parameters that are required by the Web Services
Security runtime environment via the
com.ibm.websphere.wssecurity.wssapi.WSSGenerationContext
custom property to
generate a self-issued SAMLToken.
Read about configuring a SAML token during token creation for more information about how you can
specify configuration properties to control how the token is configured.
-
Add the Thin Client for JAX-WS JAR file to the class path.
Add the app_server_root/runtimes/com.ibm.jaxws.thinclient_8.5.0.jar file to the class path. See the testing web
services-enabled clients information for more information about adding this JAR file to the class
path.
-
Use the WSSFactory newSecurityToken method to specify how to create the SAML token.
Specify the following method to create the SAML
token:
WSSFactory newSecurityToken(SAMLToken.class, callbackHandler, "system.wss.generate.saml")
Creating a SAML token requires the Java security permission
wssapi.SAMLTokenFactory.newSAMLToken. Use the PolicyTool to add the following policy statement to
the Java security policy file or the application client
was.policy file:
permission java.security.SecurityPermission "wssapi.SAMLTokenFactory.newSAMLToken
The SAMLToken.class
parameter specifies the type of security token to create.
The
callbackHandler
object contains parameters that define the characteristics
of the SAMLToken that you are creating. This object points to a SAMLGenerateCallbackHandler object
that specifies the configuration parameters described in the following table:
Table 1. SAMLGenerateCallbackHandler properties. This table describes the
configuration parameters for the SAMLGenerateCallbackHandler object using the bearer subject
confirmation method.
Property |
Description |
Required |
SamlConstants.CONFIRMATION_METHOD |
Specifies to use the Bearer confirmation method. |
Yes |
SamlConstants.TOKEN_TYPE |
Uses the constant value, WSSConstants.SAML.SAML20_VALUE_TYPE , to specify a SAML
2.0 token type.
When a web services client has policy set attachments, this property is not used by Web Services
Security runtime environment. In this scenario, specify the token value type by the valueType
attribute of the tokenGenerator binding configuration.
The example in this procedure uses a SAML 2.0 token; however, you can also use the
WSSConstants.SAML.SAML11_VALUE_TYPE value.
|
Yes |
SamlConstants.SAML_NAME_IDENTIFIER |
Specifies a user identity such as myname as the NameID value in the SAML
token.
If you do not define this parameter when using the Thin Client for JAX-WS, the NameID value does
not contain useful information.
If you are using a web services managed client, such a Java
Platform, Enterprise Edition (Java EE) application making a web services request invocation, the Web
Services Security runtime environment tries to extract user security information from the security
context. Similarly, if you do not define this parameter for a managed web services client, the
NameID value contains an UNAUTHENTICATED name identifier.
This property is not used if your web services client has policy set attachments. Read about
sending SAML tokens to learn more about sending the SAML token identity and attributes.
|
No |
SamlConstants.SIGNATURE_REQUIRED |
Specifies whether the issuer is required to digitally sign the SAML token.
A true value specifies that issuer is required to digitally sign the SAML token.
This value is the default.
|
No |
The
system.wss.generate.saml
parameter specifies the Java Authentication and Authorization Service (JAAS) login module that is used
to create the SAML token. You must specify a JVM property to define a JAAS configuration file that
contains the required JAAS login configuration; for example:
-Djava.security.auth.login.config=profile_root/properties/wsjaas_client.conf
Alternatively, you can specify a JAAS login configuration file by setting a Java system property in the sample client code; for
example:
System.setProperty("java.security.auth.login.config", "profile_root/properties/wsjaas_client.conf ");
-
Obtain the token identifier of the created SAML token.
Use the following statement as a simple test for the SAML token that you
created:
System.out.println("SAMLToken id = " + samlToken.getId())
-
Add the SAML token to the SOAP security header of a Web services request messages.
-
Initialize the web services client and configure the SOAPAction properties.
The following code snippet illustrates these
actions:
// Initialize web services client
EchoService12PortProxy echo = new EchoService12PortProxy();
echo._getDescriptor().setEndpoint(endpointURL);
// Configure SOAPAction properties
BindingProvider bp = (BindingProvider) (echo._getDescriptor().getProxy());
Map<String, Object> requestContext = bp.getRequestContext();
requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointURL);
requestContext.put(BindingProvider.SOAPACTION_USE_PROPERTY, Boolean.TRUE);
requestContext.put(BindingProvider.SOAPACTION_URI_PROPERTY, "echoOperation");
-
Initialize the WSSGenerationContext.
The following code illustrates the use of the WSSGenerationContext interface to initialize a
generation context and enable you to insert the
SAMLToken
into the web services
request
message:
// Initialize WSSGenerationContext
WSSGenerationContext gencont = factory.newWSSGenerationContext();
gencont.add(samlToken);
Specifically,
the
gencont.add(samlToken)
method call specifies to put the SAML token into a
request message. Use the PolicyTool to add the following policy statement to the Java security policy file or the application client was.policy
file:
“permission javax.security.auth.AuthPermission "modifyPrivateCredentials"
-
Add the timestamp element in the SOAP messages security header.
The SAML20 Bearer WSHTTPS default policy set requires web services requests and response
messages to carry a timestamp element in SOAP messages Security header. In the following code
snippet, the
factory.newWSSTimestamp()
method call generates the timestamp, and the
gencont.add(timestamp)
method call specifies the timestamp to put into a request
message:
// Add a timestamp to the request message.
WSSTimestamp timestamp = factory.newWSSTimestamp();
gencont.add(timestamp);
gencont.process(requestContext);
-
Attach WSSGenerationContext object to the web services RequestContext object.
The WSSGenerationContext object now contains all the security information that is required to
format a request message. The
gencont.process(requestContext)
method call attaches
the WSSGenerationContext object to the web services RequestContext object to enable the Web Services
Security runtime environment to format the required SOAP security header; for
example:
// Attaches WSSGenerationContext object to the web services RequestContext object.
gencont.process(requestContext);
-
Specify SSL transport level message protection using JVM properties.
The SAML20 Bearer WSHTTPS default policy set requires transport-level message protection using
SSL. Specify SSL transport-level message protection using the following JVM
property:
-Dcom.ibm.SSL.ConfigURL=file:profile_root
\properties\ssl.client.props
Alternatively, you can define the SSL configuration file using a Java system property in the sample client code; for
example:
System.setProperty("com.ibm.SSL.ConfigURL", "file:profile_root/properties/ssl.client.props");
Results
You have created a self-issued SAML token with the bearer subject confirmation method and then
sent this token with web services request messages using the JAX-WS programming model and WSS
APIs.
Example
The following code sample is a web services client application that demonstrates how to create a
self-issued SAML token and send that SAML token in web services request messages. If your usage
scenario requires SAML tokens, but does not require your application to pass the SAML tokens using
web services messages, you only need to use the first part of the following sample code, up through
the // Initialize web services client
section.
/**
* The following source code is sample code created by IBM Corporation.
* This sample code is provided to you solely for the purpose of assisting you in the
* use of the technology. The code is provided 'AS IS', without warranty or condition of
* any kind. IBM shall not be liable for any damages arising out of your use of the
* sample code, even if IBM has been advised of the possibility of such damages.
*/
package com.ibm.was.wssample.sei.cli;
import com.ibm.was.wssample.sei.echo.EchoService12PortProxy;
import com.ibm.was.wssample.sei.echo.EchoStringInput;
import com.ibm.websphere.wssecurity.wssapi.WSSFactory;
import com.ibm.websphere.wssecurity.wssapi.WSSGenerationContext;
import com.ibm.websphere.wssecurity.wssapi.WSSConsumingContext;
import com.ibm.websphere.wssecurity.wssapi.WSSTimestamp;
import com.ibm.websphere.wssecurity.callbackhandler.SAMLGenerateCallbackHandler;
import com.ibm.websphere.wssecurity.wssapi.token.SAMLToken;
import com.ibm.websphere.wssecurity.wssapi.token.SecurityToken;
import com.ibm.wsspi.wssecurity.core.token.config.WSSConstants;
import com.ibm.wsspi.wssecurity.saml.config.SamlConstants;
import java.util.Map;
import java.util.HashMap;
import javax.xml.ws.BindingProvider;
/**
* SampleClient
* main entry point for thin client JAR sample
* and worker class to communicate with the services
*/
public class SampleClient {
private String urlHost = "localhost";
private String urlPort = "9443";
private static final String CONTEXT_BASE = "/WSSampleSei/";
private static final String ECHO_CONTEXT12 = CONTEXT_BASE+"EchoService12";
private String message = "HELLO";
private String uriString = "https://" + urlHost + ":" + urlPort;
private String endpointURL = uriString + ECHO_CONTEXT12;
private String input = message;
/**
* main()
*
* see printusage() for command-line arguments
*
* @param args
*/
public static void main(String[] args) {
SampleClient sample = new SampleClient();
sample.CallService();
}
/**
* CallService Parms were already read. Now call the service proxy classes
*
*/
void CallService() {
String response = "ERROR!:";
try {
System.setProperty("java.security.auth.login.config", "profile_root/properties/wsjaas_client.conf ");
System.setProperty("com.ibm.SSL.ConfigURL", "file:profile_root/properties/ssl.client.props");
// Initialize WSSFactory object
WSSFactory factory = WSSFactory.getInstance();
// Initialize WSSGenerationContext
WSSGenerationContext gencont = factory.newWSSGenerationContext();
// Initialize SAML issuer configuration via custom properties
HashMap<Object, Object> customProps = new HashMap<Object,Object>();
customProps.put(SamlConstants.ISSUER_URI_PROP, "example.com");
customProps.put(SamlConstants.TTL_PROP, "3600000");
customProps.put(SamlConstants.KS_PATH_PROP, "keystores/saml-provider.jceks");
customProps.put(SamlConstants.KS_TYPE_PROP, "JCEKS");
customProps.put(SamlConstants.KS_PW_PROP, "{xor}LCswLTovPiws");
customProps.put(SamlConstants.KEY_ALIAS_PROP, "samlissuer");
customProps.put(SamlConstants.KEY_NAME_PROP, "CN=SAMLIssuer, O=EXAMPLE");
customProps.put(SamlConstants.KEY_PW_PROP, "{xor}NDomLz4sLA==");
customProps.put(SamlConstants.TS_PATH_PROP, "keystores/saml-provider.jceks");
customProps.put(SamlConstants.TS_TYPE_PROP, "JCEKS");
customProps.put(SamlConstants.TS_PW_PROP, "{xor}LCswLTovPiws");
gencont.add(customProps); //Add custom properties
// Create SAMLToken
HashMap<Object, Object> map = new HashMap<Object, Object>();
map.put(SamlConstants.CONFIRMATION_METHOD, "Bearer");
map.put(SamlConstants.TOKEN_TYPE, WSSConstants.SAML.SAML20_VALUE_TYPE);
map.put(SamlConstants.SAML_NAME_IDENTIFIER, "Alice");
map.put(SamlConstants.SIGNATURE_REQUIRED, "true");
SAMLGenerateCallbackHandler callbackHandler = new SAMLGenerateCallbackHandler(map);
SecurityToken samlToken = factory.newSecurityToken(SAMLToken.class, callbackHandler, "system.wss.generate.saml");
System.out.println("SAMLToken id = " + samlToken.getId());
// Initialize web services client
EchoService12PortProxy echo = new EchoService12PortProxy();
echo._getDescriptor().setEndpoint(endpointURL);
// Configure SOAPAction properties
BindingProvider bp = (BindingProvider) (echo._getDescriptor().getProxy());
Map<String, Object> requestContext = bp.getRequestContext();
requestContext.put(BindingProvider.ENDPOINT_ADDRESS_PROPERTY, endpointURL);
requestContext.put(BindingProvider.SOAPACTION_USE_PROPERTY, Boolean.TRUE);
requestContext.put(BindingProvider.SOAPACTION_URI_PROPERTY, "echoOperation");
gencont.add(samlToken);
// Add timestamp
WSSTimestamp timestamp = factory.newWSSTimestamp();
gencont.add(timestamp);
gencont.process(requestContext);
// Build the input object
EchoStringInput echoParm =
new com.ibm.was.wssample.sei.echo.ObjectFactory().createEchoStringInput();
echoParm.setEchoInput(input);
System.out.println(">> CLIENT: SEI Echo to " + endpointURL);
// Prepare to consume timestamp in response message.
WSSConsumingContext concont = factory.newWSSConsumingContext();
concont.add(WSSConsumingContext.TIMESTAMP);
concont.process(requestContext);
// Call the service
response = echo.echoOperation(echoParm).getEchoResponse();
System.out.println(">> CLIENT: SEI Echo invocation complete.");
System.out.println(">> CLIENT: SEI Echo response is: " + response);
} catch (Exception e) {
System.out.println(">> CLIENT: ERROR: SEI Echo EXCEPTION.");
e.printStackTrace();
}
}
}
When this web services client application sample runs correctly, you receive messages like the
following
messages:
SAMLToken id = _191EBC44865015D9AB1270745072344
Retrieving document at 'file:profile_root/.../wsdl/'.
>> CLIENT: SEI Echo to https://localhost:9443/WSSampleSei/EchoService12
>> CLIENT: SEI Echo invocation complete.
>> CLIENT: SEI Echo response is: SOAP12==>>HELLO