You can create self-issued SAML tokens with the sender-vouches
subject confirmation method and then use the Java API for XML-Based Web Services (JAX-WS)
programming model and Web Services Security APIs (WSS APIs) to send
these tokens with web services request messages with transport protection.
Before you begin
This task assumes that you are familiar with the JAX-WS
programming model, the WSS API interfaces, SAML concepts, SSL transport
protection, 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 sender-vouches 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 sender-vouches subject confirmation using
message protection at the transport level 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 client
application 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 examples 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 use the Web Services Security API to pass SAML
sender-vouches 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.
- Create a copy of either the SAML20 Bearer WSHTTPS default
policy set or the SAML11 Bearer WSHTTPS default policy set.
Provide
a name for the copy of the policy set; for example SAML20 SenderVouches
WSHTTPS or SAML11 SenderVouches WSHTTPS to help you identify that
this new policy set uses the sender-vouches confirmation method.
No
additional change is required to the new policy file because the subject
confirmation method is specified in the binding configuration and
not in the policy.
The new policy file contains either SAMLToken20Bearer
or the SAMLToken11Bearer as the policy identifiers. Change the identifier
of the SAMLToken20Bearer policy to SAMLToken20SV or change the identifier
of the SAMLToken11Bearer policy to SAMLToken11SV to specify a more
descriptive name. Changing the identifier of the policy does not change
the policy enforcement in any way; however, adding a descriptive identifier
helps you to identify that these policy identifiers use the sender-vouches
confirmation method.
If you want to view the settings of these
policies, use the administrative console to complete the following
actions:
- Click .
- Click the WS-Security policy in the policies
table.
- Click the Main policy link or the Bootstrap
policy link.
- Click Request token policies from the Policy
Details section.
- Attach the new SAML20 SenderVouches WSHTTPS or SAML11 SenderVouches
WSHTTPS policy set to the web services provider application. Read
about configuring client and provider bindings for the SAML sender-vouches
token for details on attaching this policy set to your web services
provider application.
- Create a copy of the SAML Bearer Provider sample default
general bindings.
- For the new copy of the default policy set, provide
a name that includes sender-vouches, such as SAML Sender-vouches
provider binding.
- Change the value of the confirmationMethod property
to sender-vouches in the token consumer configuration
for the intended SAML token version. Read about configuring
client and provider bindings for the SAML sender-vouches token for
details on modifying the sender-vouches bindings to satisfy the vouching
requirement.
- Assign the new provider binding to the JaxWSServicesSamples
provider sample. Read about configuring client and provider
bindings for the SAML sender-vouches for details on assigning the
SAML sender-vouches provider sample, default general bindings to your
web services provider application.
- Enable the web services provider SSL configuration attribute,
clientAuthentication, to require X.509 client certificate authentication.
The clientAuthentication attribute determines whether SSL
client authentication is required. To specify the clientAuthentication
attribute, use the administrative console to complete the following
actions:
- Click .
- Click the WC_defaulthost_secure link.
- Under Related Items, click the SSL_configurations link.
- Select the NodeDefaultSSLSettings resource.
- Click Quality of protection (QoP) settings link.
- Select Required from the menu to specify
client authentication.
Read about creating a secure sockets layer configuration
to learn more about configuring the clientAuthentication attribute.
- In the web services client code, use the CallService()
method to specify the properties file that contains configuration
parameters required to generate a self-issued SAML token.
The
CallService() method specifies configuration parameters that are required
by the Web Services Security runtime environment to generate a self-issued
SAMLToken.
The following code snippet illustrates using the
CallService() method to specify Web services security configuration
parameters:
public static void main(String[] args) {
SampleSamlSVClient sample = new SampleSamlSVClient();
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 ");
// 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
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 classpath. Add app_server_root/runtimes/com.ibm.jaxws.thinclient_8.5.0.jar
file to the classpath. See the testing web services-enabled clients
information for more information about adding this JAR file to the
classpath.
- Create the self-issued SAML token. The following
code snippet illustrates creating the SAML sender-vouches token:
// Create SAMLToken
HashMap<Object, Object> map = new HashMap<Object, Object>();
map.put(SamlConstants.CONFIRMATION_METHOD, "sender-vouches");
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());
- 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 sender-vouches
confirmation method.Property |
Description |
Required |
SamlConstants.CONFIRMATION_METHOD |
Specifies to use the sender-vouches 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 SAMLToken.
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())
Results
You have created a self-issued SAML token with the sender-vouches
confirmation method with transport protection 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 complete, ready-to-use
web services client application that demonstrates how to create a
self-issued SAML sender-vouches token and send that SAML token in
web services request messages. This sample code illustrates the procedure
steps described previously.
/**
* 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;
public class SampleSamlSVClient {
private String urlHost = "localhost";
private String urlPort = "9081";
private static final String CONTEXT_BASE = "/WSSampleSei/";
private static final String ECHO_CONTEXT12 = CONTEXT_BASE+"EchoService12";
private String message = "HELLO";
private String uriString = "http://" + 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) {
SampleSamlSVClient sample = new SampleSamlSVClient();
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 ");
// 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, "sender-vouches");
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 = _6CDDF0DBF91C044D211271166233407
Retrieving document at 'file:profile_root/.../wsdl/'.
>> CLIENT: SEI Echo to http://localhost:9443/WSSampleSei/EchoService12
>> CLIENT: SEI Echo invocation complete.
>> CLIENT: SEI Echo response is: SOAP12==>>HELLO