Network Deployment (Distributed operating systems), v8.0 > Develop and deploying applications > Develop web services - Security (WS-Security) > Develop applications that use Web Services Security > Develop message-level security for JAX-WS web services > Secure web services applications using the WSS APIs at the message level > Secure messages at the request generator using WSS APIs > Secure messages at the request generator using WSS APIs


Send self-issued SAML holder-of-key tokens with asymmetric key using WSS APIs

We can create self-issued SAML tokens with the holder-of-key subject confirmation method and then use the JAX-WS programming model and Web Services Security APIs (WSS APIs) to send these tokens with web services request messages.

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. Complete the following actions before you begin this task:

This task focuses on using the asymmetric key that is identified by SAML security tokens to generate a digital signature of selected SOAP message elements in order to satisfy holder-of-key subject confirmation method security requirements. The X.509 certificate of the sender is embedded in the SAML security token. The sender signs selected parts of request message elements by using its corresponding private key and encrypts the request message by using the public key of the recipient. The recipient signs the selected elements of the response message by using the private key of the recipient, and encrypts selected elements of the response message by using the public key of the sender in SAML security tokens. The Web services security policy attached to the web services provider is provided for your reference.


Procedure

  1. Create a SAML security token that contains the holder-of-key subject confirmation method; for example:
    WSSFactory factory = WSSFactory.getInstance();
    // Initialize WSSGenerationContext
    com.ibm.websphere.wssecurity.wssapi.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 HashMap
    <Object, Object> map = new HashMap
    <Object, Object>();
    map.put(SamlConstants.CONFIRMATION_METHOD, "holder-of-key");
    map.put(SamlConstants.Token_REQUEST, "issue");
    map.put(SamlConstants.TOKEN_TYPE, WSSConstants.SAML.SAML20_VALUE_TYPE);
    map.put(SamlConstants.SAML_NAME_IDENTIFIER, "Alice");
    map.put(SamlConstants.SIGNATURE_REQUIRED, "true");
    map.put(SamlConstants.KEY_TYPE,
            "http://docs.oasis-open.org/ws-sx/ws-trust/200512/PublicKey");
    map.put(SamlConstants.SAML_APPLIES_TO, "http://localhost:9080/your_Web_service");
    map.put(SamlConstants.KEY_ALIAS, "soapinitiator" );
    map.put(SamlConstants.KEY_NAME, "CN=SOAPInitator, O=ACME");
    map.put(SamlConstants.KEY_PASSWORD, "keypass");
    map.put(SamlConstants.KEY_STORE_PATH, "keystores/initiator.jceks");
    map.put(SamlConstants.KEY_STORE_PASSWORD, "storepass");
    map.put(SamlConstants.KEY_STORE_TYPE, "jceks");
    SAMLGenerateCallbackHandler callbackHandler = new SAMLGenerateCallbackHandler(map);
    SAMLToken samlToken = (SAMLToken) factory.newSecurityToken(SAMLToken.class,                       callbackHandler, "system.wss.generate.saml");
    

    The private key of the sender is specified by the SamlConstants.KEY_ALIAS property and is used to sign selected elements of the request message.

  2. Use the WSSGenerationContext object to prepare for request message security header processing; for example:
    gencon.add(samlToken); //this line of code can be omitted
    WSSTimestamp timestamp = factory.newWSSTimestamp();
    gencon.add(timestamp);
    WSSSignature sig = factory.newWSSSignature(samlToken);
    sig.setTokenReference(SecurityToken.REF_KEYID);
    //If the gencon.add(samlToken); line of code is omitted, //the above line of code must be replaced with //sig.setTokenReference(SecurityToken.REF_STR);
    
    sig.setSignatureMethod(WSSSignature.RSA_SHA1);
    sig.setCanonicalizationMethod(WSSSignature.EXC_C14N);
    sig.addSignPart(WSSSignature.BODY);
    sig.addSignPart(WSSSignature.TIMESTAMP);
    sig.addSignPart(WSSSignature.ADDRESSING_HEADERS);
    gencon.add(sig);
    X509GenerateCallbackHandler x509callbackHandler2 = new X509GenerateCallbackHandler(
            null,
            "keystores/initiator.jceks",
            "jceks",         "storepass".toCharArray(),
            "soaprecipient",         null,
            "", null);
    SecurityToken st2 = factory.newSecurityToken(X509Token.class, x509callbackHandler2);
    WSSEncryption enc = factory.newWSSEncryption(st2);
    enc.addEncryptPart(WSSEncryption.BODY_CONTENT);
    enc.addEncryptPart(WSSEncryption.SIGNATURE);
    enc.setEncryptionMethod(WSSEncryption.AES256);
    enc.setKeyEncryptionMethod(WSSEncryption.KW_RSA_OAEP);
    gencon.add(enc);
    

    In this example, encryption uses a 256 bit key size so import the Java Cryptography Extension (JCE) policy file. For more information, read about using the unrestricted JCE policy files in the "Tuning Web Services Security applications" topic.

  3. Create the WSSConsumingContext object to prepare for response message security header processing; for example:
    WSSConsumingContext concont = factory.newWSSConsumingContext();
    
    HashMap
    <Object, Object> map = new HashMap
    <Object, Object>();
    
    SAMLConsumerCallbackHandler callbackHandler = new SAMLConsumerCallbackHandler(map);
    WSSDecryption dec = factory.newWSSDecryption(SAMLToken.class, callbackHandler,                             "system.wss.consume.saml");
    dec.addAllowedEncryptionMethod(WSSDecryption.AES256);
    dec.addAllowedKeyEncryptionMethod(WSSDecryption.KW_RSA_OAEP);
    dec.encryptKey(false);
    dec.addRequiredDecryptPart(WSSDecryption.BODY_CONTENT);
    concont.add(dec);
    X509ConsumeCallbackHandler verHandler = new X509ConsumeCallbackHandler(null,
                "keystores/initiator.jceks",             "jceks",             "storepass".toCharArray(),             "soaprecipient",             null, null);
    WSSVerification ver = factory.newWSSVerification(X509Token.class, verHandler);
    ver.addRequiredVerifyPart(WSSVerification.BODY);
    concont.add(ver);
    

  4. Use the JDK keytool utility to generate the saml-provider.jceks, initiator.jceks, and recipient.jceksfiles that are used to test the example code; for example:
    keytool -genkey -alias samlissuer -keystore saml-provider.jceks -dname "CN=SAMLIssuer, O=ACME" -storepass storepass -keypass keypass
     -storetype jceks -validity 5000 -keyalg RSA -keysize 2048
    
    keytool -genkey -alias soaprecipient -keystore recipient.jceks -dname "CN=SOAPRecipient, O=ACME" -storepass storepass -keypass keypass
     -storetype jceks -validity 5000 -keyalg RSA -keysize 2048
    
    keytool -genkey -alias soapinitiator -keystore initiator.jceks -dname "CN=SOAPInitator, O=ACME" -storepass storepass -keypass keypass
     -storetype jceks -validity 5000 -keyalg RSA -keysize 2048
    
    keytool -export -alias samlissuer -file issuerpub.cer -keystore saml-provider.jceks -storepass storepass -storetype jceks
    keytool -export -alias soaprecipient -file reciptpub.cer -keystore recipient.jceks -storepass storepass -storetype jceks
    keytool -export -alias soapinitiator -file initatpub.cer -keystore initiator.jceks -storepass storepass -storetype jceks
    
    keytool -import -alias samlissuer -file issuerpub.cer -keystore initiator.jceks -storepass storepass -storetype jceks -keypass keypass -noprompt
    keytool -import -alias soaprecipient -file reciptpub.cer -keystore initiator.jceks -storepass storepass -storetype jceks -keypass keypass -noprompt
    
    keytool -import -alias samlissuer -file issuerpub.cer -keystore recipient.jceks -storepass storepass -storetype jceks -keypass keypass -noprompt
    keytool -import -alias soapinitiator -file initatpub.cer -keystore recipient.jceks -storepass storepass -storetype jceks -keypass keypass -noprompt
    
    keytool -import -alias soapinitiator -file initatpub.cer -keystore saml-provider.jceks -storepass storepass -storetype jceks -keypass keypass -noprompt
    


Results

You have learned key building blocks to create a web services client application to send a SAML security token in a SOAP message and to use the asymmetric key that is embedded in SAML security in message level protection.


Example

The following example illustrates the web services provider Web services security policy:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<wsp:Policy xmlns:wsp="http://schemas.xmlsoap.org/ws/2004/09/policy"
  xmlns:wsu="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd"
  xmlns:sp="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200512" xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/08/addressing"
  xmlns:spe="http://www.ibm.com/xmlns/prod/websphere/200605/ws-securitypolicy-ext">
<wsp:Policy wsu:Id="response:app_encparts">  
<sp:EncryptedElements>      
<sp:XPath>/*[namespace-uri()='http://schemas.xmlsoap.org/soap/envelope/'
             and local-name()='Envelope']/*[namespace-uri()='http://schemas.xmlsoap.org/soap/envelope/'
             and local-name()='Header']/*[namespace-uri()='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
             and local-name()='Security']/*[namespace-uri()='http://www.w3.org/2000/09/xmldsig#' and local-name()='Signature']
</sp:XPath>      
<sp:XPath>/*[namespace-uri()='http://www.w3.org/2003/05/soap-envelope'
             and local-name()='Envelope']/*[namespace-uri()='http://www.w3.org/2003/05/soap-envelope'
             and local-name()='Header']/*[namespace-uri()='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
             and local-name()='Security']/*[namespace-uri()='http://www.w3.org/2000/09/xmldsig#' and local-name()='Signature']
</sp:XPath>  
</sp:EncryptedElements>  
<sp:EncryptedParts>      
<sp:Body/>  
</sp:EncryptedParts>
</wsp:Policy>
<wsp:Policy wsu:Id="request:req_enc">  
<sp:EncryptedParts>      
<sp:Body/>  
</sp:EncryptedParts>
</wsp:Policy>
<wsp:Policy wsu:Id="request:app_signparts">  
<sp:SignedParts>      
<sp:Body/>      
<sp:Header Namespace="http://schemas.xmlsoap.org/ws/2004/08/addressing"/>      
<sp:Header Namespace="http://www.w3.org/2005/08/addressing"/>  
</sp:SignedParts>  
<sp:SignedElements>      
<sp:XPath>/*[namespace-uri()='http://schemas.xmlsoap.org/soap/envelope/'
             and local-name()='Envelope']/*[namespace-uri()='http://schemas.xmlsoap.org/soap/envelope/'
             and local-name()='Header']/*[namespace-uri()='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
             and local-name()='Security']/*[namespace-uri()='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'
             and local-name()='Timestamp']
</sp:XPath>      
<sp:XPath>/*[namespace-uri()='http://www.w3.org/2003/05/soap-envelope'
            and local-name()='Envelope']/*[namespace-uri()='http://www.w3.org/2003/05/soap-envelope'
            and local-name()='Header']/*[namespace-uri()='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd'
            and local-name()='Security']/*[namespace-uri()='http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd'
            and local-name()='Timestamp']
</sp:XPath>  
</sp:SignedElements>
</wsp:Policy>
<wsp:Policy wsu:Id="response:resp_sig">  
<sp:SignedParts>      
<sp:Body/>  
</sp:SignedParts>
</wsp:Policy>
<sp:AsymmetricBinding>  
<wsp:Policy>      
<sp:InitiatorToken>          
<wsp:Policy>              
<spe:CustomToken sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200512/IncludeToken/Always"/>                  
<wsp:Policy>                      
<spe:WssCustomToken localname="http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0"/>                  
</wsp:Policy>              
</spe:CustomToken>          
</wsp:Policy>      
</sp:InitiatorToken>      
<sp:AlgorithmSuite>          
<wsp:Policy>              
<sp:Basic256/>          
</wsp:Policy>      
</sp:AlgorithmSuite>      
<sp:IncludeTimestamp/>      
<sp:RecipientToken>          
<wsp:Policy>              
<sp:X509Token sp:IncludeToken="http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200512/IncludeToken/Always"/>                  
<wsp:Policy>                      
<sp:WssX509V3Token11/>                  
</wsp:Policy>              
</sp:X509Token>          
<wsp:Policy>      
<sp:RecipientToken>      
<sp:Layout>          
<wsp:Policy>              
<sp:Strict/>          
</wsp:Policy>      
</sp:Layout>  
<wsp:Policy>
<sp:AsymmetricBinding>
</wsp:Policy> 

SAML concepts
Configure client and provider bindings for the SAML bearer token
Send self-issued SAML bearer tokens using WSS APIs
Send self-issued SAML holder-of-key tokens with symmetric key using WSS APIs
Tune Web Services Security for v8.0 applications
Manage self-issue SAML token configuration using wsadmin


Related


Web Services Security APIs

+

Search Tips   |   Advanced Search