View Javadoc
1   /**
2    * Licensed to the Apache Software Foundation (ASF) under one
3    * or more contributor license agreements. See the NOTICE file
4    * distributed with this work for additional information
5    * regarding copyright ownership. The ASF licenses this file
6    * to you under the Apache License, Version 2.0 (the
7    * "License"); you may not use this file except in compliance
8    * with the License. You may obtain a copy of the License at
9    *
10   * http://www.apache.org/licenses/LICENSE-2.0
11   *
12   * Unless required by applicable law or agreed to in writing,
13   * software distributed under the License is distributed on an
14   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15   * KIND, either express or implied. See the License for the
16   * specific language governing permissions and limitations
17   * under the License.
18   */
19  package org.apache.wss4j.stax.test.saml;
20  
21  import java.io.ByteArrayInputStream;
22  import java.io.ByteArrayOutputStream;
23  import java.io.InputStream;
24  import java.nio.charset.StandardCharsets;
25  import java.security.KeyStore;
26  import java.util.ArrayList;
27  import java.util.List;
28  import java.util.Properties;
29  
30  import javax.crypto.KeyGenerator;
31  import javax.crypto.SecretKey;
32  import javax.xml.stream.XMLStreamReader;
33  import javax.xml.stream.XMLStreamWriter;
34  import javax.xml.transform.dom.DOMSource;
35  import javax.xml.transform.stream.StreamResult;
36  
37  import org.apache.wss4j.common.WSEncryptionPart;
38  import org.apache.wss4j.common.crypto.Crypto;
39  import org.apache.wss4j.common.crypto.CryptoFactory;
40  import org.apache.wss4j.common.crypto.CryptoType;
41  import org.apache.wss4j.common.crypto.Merlin;
42  import org.apache.wss4j.common.saml.SAMLCallback;
43  import org.apache.wss4j.common.saml.SAMLUtil;
44  import org.apache.wss4j.common.saml.SamlAssertionWrapper;
45  import org.apache.wss4j.common.saml.bean.Version;
46  import org.apache.wss4j.common.saml.builder.SAML1Constants;
47  import org.apache.wss4j.common.saml.builder.SAML2Constants;
48  import org.apache.wss4j.common.util.KeyUtils;
49  import org.apache.wss4j.common.util.SOAPUtil;
50  import org.apache.wss4j.dom.WSConstants;
51  import org.apache.wss4j.dom.handler.WSHandlerConstants;
52  import org.apache.wss4j.dom.message.WSSecEncrypt;
53  import org.apache.wss4j.dom.message.WSSecHeader;
54  import org.apache.wss4j.dom.saml.WSSecSignatureSAML;
55  import org.apache.wss4j.stax.ext.WSSConstants;
56  import org.apache.wss4j.stax.ext.WSSSecurityProperties;
57  import org.apache.wss4j.stax.securityEvent.WSSecurityEventConstants;
58  import org.apache.wss4j.stax.securityToken.WSSecurityTokenConstants;
59  import org.apache.wss4j.stax.setup.InboundWSSec;
60  import org.apache.wss4j.stax.setup.OutboundWSSec;
61  import org.apache.wss4j.stax.setup.WSSec;
62  import org.apache.wss4j.stax.test.AbstractTestBase;
63  import org.apache.wss4j.stax.test.CallbackHandlerImpl;
64  import org.apache.wss4j.stax.test.utils.StAX2DOM;
65  import org.apache.wss4j.stax.test.utils.XmlReaderToWriter;
66  import org.apache.xml.security.stax.securityEvent.SecurityEvent;
67  import org.junit.jupiter.api.Test;
68  import org.w3c.dom.Document;
69  import org.w3c.dom.Element;
70  import org.w3c.dom.Node;
71  import org.w3c.dom.NodeList;
72  
73  import static org.junit.jupiter.api.Assertions.assertEquals;
74  
75  public class SAMLTokenReferenceTest extends AbstractTestBase {
76  
77      @Test
78      public void testSAML1SVKeyIdentifierOutbound() throws Exception {
79  
80          ByteArrayOutputStream baos = new ByteArrayOutputStream();
81          {
82              WSSSecurityProperties securityProperties = new WSSSecurityProperties();
83              List<WSSConstants.Action> actions = new ArrayList<>();
84              actions.add(WSSConstants.SAML_TOKEN_SIGNED);
85              securityProperties.setActions(actions);
86              SAMLCallbackHandlerImpl callbackHandler = new SAMLCallbackHandlerImpl();
87              callbackHandler.setStatement(SAMLCallbackHandlerImpl.Statement.AUTHN);
88              callbackHandler.setConfirmationMethod(SAML1Constants.CONF_SENDER_VOUCHES);
89              callbackHandler.setIssuer("www.example.com");
90              callbackHandler.setSignAssertion(false);
91              securityProperties.setSamlCallbackHandler(callbackHandler);
92              securityProperties.setSignatureKeyIdentifier(WSSecurityTokenConstants.KeyIdentifier_SkiKeyIdentifier);
93              securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
94              securityProperties.setSignatureUser("transmitter");
95              securityProperties.setCallbackHandler(new CallbackHandlerImpl());
96  
97              OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
98              XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
99              XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
100             XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
101             xmlStreamWriter.close();
102 
103             Document document = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
104             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
105             assertEquals(nodeList.getLength(), 1);
106             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
107 
108             nodeList = document.getElementsByTagNameNS("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "KeyIdentifier");
109             assertEquals(nodeList.getLength(), 2);
110             assertEquals(((Element) nodeList.item(0)).getAttributeNS(null, "ValueType"), "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID");
111             assertEquals(((Element) nodeList.item(1)).getAttributeNS(null, "ValueType"), "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509SubjectKeyIdentifier");
112         }
113 
114         //done signature; now test sig-verification:
115         {
116             String action = WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.SAML_TOKEN_UNSIGNED;
117             Properties properties = new Properties();
118             doInboundSecurityWithWSS4J_1(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action, properties, false);
119         }
120     }
121 
122     @Test
123     public void testSAML1SVKeyIdentifierInbound() throws Exception {
124 
125         ByteArrayOutputStream baos = new ByteArrayOutputStream();
126         {
127             SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
128             callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
129             callbackHandler.setConfirmationMethod(SAML1Constants.CONF_SENDER_VOUCHES);
130             callbackHandler.setIssuer("www.example.com");
131             callbackHandler.setSignAssertion(false);
132 
133             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
134             String action = WSHandlerConstants.SAML_TOKEN_SIGNED;
135             Properties properties = new Properties();
136             properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
137             properties.setProperty(WSHandlerConstants.SIG_KEY_ID, "X509KeyIdentifier");
138             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
139 
140             //some test that we can really sure we get what we want from WSS4J
141             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
142             assertEquals(nodeList.getLength(), 1);
143             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
144 
145             nodeList = securedDocument.getElementsByTagNameNS("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "KeyIdentifier");
146             assertEquals(nodeList.getLength(), 2);
147             assertEquals(((Element) nodeList.item(0)).getAttributeNS(null, "ValueType"), "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID");
148             assertEquals(((Element) nodeList.item(1)).getAttributeNS(null, "ValueType"), "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3");
149 
150             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
151             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
152         }
153 
154         //done signature; now test sig-verification:
155         {
156             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
157             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
158             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
159 
160             WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
161                     WSSecurityEventConstants.AlgorithmSuite,
162                     WSSecurityEventConstants.AlgorithmSuite,
163                     WSSecurityEventConstants.AlgorithmSuite,
164                     WSSecurityEventConstants.AlgorithmSuite,
165                     WSSecurityEventConstants.AlgorithmSuite,
166                     WSSecurityEventConstants.AlgorithmSuite,
167                     WSSecurityEventConstants.SAML_TOKEN,
168                     WSSecurityEventConstants.X509Token,
169                     WSSecurityEventConstants.SignatureValue,
170                     WSSecurityEventConstants.SignedElement,
171                     WSSecurityEventConstants.SIGNED_PART,
172                     WSSecurityEventConstants.OPERATION,
173             };
174             final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
175             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), null, securityEventListener);
176 
177             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
178 
179             securityEventListener.compare();
180 
181             //header element must still be there
182             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
183             assertEquals(nodeList.getLength(), 1);
184         }
185     }
186 
187     @Test
188     public void testSAML1HOKKeyIdentifierOutbound() throws Exception {
189 
190         ByteArrayOutputStream baos = new ByteArrayOutputStream();
191         {
192             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
193             List<WSSConstants.Action> actions = new ArrayList<>();
194             actions.add(WSSConstants.SAML_TOKEN_SIGNED);
195             securityProperties.setActions(actions);
196             SAMLCallbackHandlerImpl callbackHandler = new SAMLCallbackHandlerImpl();
197             callbackHandler.setStatement(SAMLCallbackHandlerImpl.Statement.AUTHN);
198             callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
199             callbackHandler.setIssuer("www.example.com");
200             KeyStore keyStore = KeyStore.getInstance("jks");
201             keyStore.load(this.getClass().getClassLoader().getResourceAsStream("transmitter.jks"), "default".toCharArray());
202             Merlin crypto = new Merlin();
203             crypto.setKeyStore(keyStore);
204             CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
205             cryptoType.setAlias("transmitter");
206             callbackHandler.setCerts(crypto.getX509Certificates(cryptoType));
207             securityProperties.setSamlCallbackHandler(callbackHandler);
208             securityProperties.setSignatureKeyIdentifier(WSSecurityTokenConstants.KEYIDENTIFIER_EMBEDDED_KEY_IDENTIFIER_REF);
209             securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
210             securityProperties.setSignatureUser("transmitter");
211             securityProperties.setCallbackHandler(new CallbackHandlerImpl());
212 
213             OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
214             XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
215             XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
216             XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
217             xmlStreamWriter.close();
218 
219             Document document = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
220             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
221             assertEquals(nodeList.getLength(), 2);
222             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_SAML_ASSERTION.getLocalPart());
223             assertEquals(nodeList.item(1).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
224 
225             nodeList = document.getElementsByTagNameNS("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "KeyIdentifier");
226             assertEquals(nodeList.getLength(), 1);
227             assertEquals(((Element) nodeList.item(0)).getAttributeNS(null, "ValueType"), "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID");
228         }
229 
230         //done signature; now test sig-verification:
231         {
232             String action = WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.SAML_TOKEN_SIGNED;
233             Properties properties = new Properties();
234             doInboundSecurityWithWSS4J_1(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action, properties, false);
235         }
236     }
237 
238     @Test
239     public void testSAML1HOKKeyIdentifierInbound() throws Exception {
240 
241         ByteArrayOutputStream baos = new ByteArrayOutputStream();
242         {
243             SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
244             callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
245             callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
246             callbackHandler.setIssuer("www.example.com");
247 
248             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
249             String action = WSHandlerConstants.SAML_TOKEN_SIGNED;
250             Properties properties = new Properties();
251             properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
252             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
253 
254             //some test that we can really sure we get what we want from WSS4J
255             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
256             assertEquals(nodeList.getLength(), 2);
257             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_SAML_ASSERTION.getLocalPart());
258             assertEquals(nodeList.item(1).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
259 
260             nodeList = securedDocument.getElementsByTagNameNS("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "KeyIdentifier");
261             assertEquals(nodeList.getLength(), 1);
262             assertEquals(((Element) nodeList.item(0)).getAttributeNS(null, "ValueType"), "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID");
263 
264             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
265             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
266         }
267 
268         //done signature; now test sig-verification:
269         {
270             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
271             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
272             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
273 
274             WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
275                     WSSecurityEventConstants.AlgorithmSuite,
276                     WSSecurityEventConstants.AlgorithmSuite,
277                     WSSecurityEventConstants.AlgorithmSuite,
278                     WSSecurityEventConstants.AlgorithmSuite,
279                     WSSecurityEventConstants.AlgorithmSuite,
280                     WSSecurityEventConstants.SAML_TOKEN,
281                     WSSecurityEventConstants.SignatureValue,
282                     WSSecurityEventConstants.SIGNED_PART,
283                     WSSecurityEventConstants.OPERATION,
284             };
285             final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
286             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), null, securityEventListener);
287 
288             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
289 
290             securityEventListener.compare();
291 
292             //header element must still be there
293             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
294             assertEquals(nodeList.getLength(), 2);
295         }
296     }
297 
298     /* todo doesn't work atm
299     @Test
300     public void testAssertionBelowSTRInbound() throws Exception {
301 
302         ByteArrayOutputStream baos = new ByteArrayOutputStream();
303         {
304             SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
305             callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
306             callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
307             callbackHandler.setIssuer("www.example.com");
308 
309             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
310             String action = WSHandlerConstants.SAML_TOKEN_SIGNED;
311             Properties properties = new Properties();
312             properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
313             properties.setProperty(WSHandlerConstants.SIG_KEY_ID, "DirectReference");
314             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
315 
316             //some test that we can really sure we get what we want from WSS4J
317             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
318             assertEquals(nodeList.getLength(), 2);
319             Element securityHeader = (Element) nodeList.item(1).getParentNode();
320             nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_SAML_ASSERTION.getNamespaceURI(), WSSConstants.TAG_saml_Assertion.getLocalPart());
321             Node assertionNode = nodeList.item(0);
322             securityHeader.removeChild(assertionNode);
323             securityHeader.appendChild(assertionNode);
324 
325             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
326             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
327             transformer.transform(new DOMSource(securedDocument), new StreamResult(System.out));
328         }
329 
330         //done signature; now test sig-verification:
331         {
332             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
333             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
334             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
335             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
336 
337             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
338 
339             //header element must still be there
340             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
341             assertEquals(nodeList.getLength(), 2);
342         }
343     }
344 */
345 
346     @Test
347     public void testSAML1HOKEKKeyIdentifierInbound() throws Exception {
348 
349         ByteArrayOutputStream baos = new ByteArrayOutputStream();
350         {
351             SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
352             //we set here the receiver's certificate just to test EncryptedKey references.
353             //in real life this wont work that way.
354             CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
355             cryptoType.setAlias("receiver");
356             callbackHandler.setCerts(CryptoFactory.getInstance("transmitter-crypto.properties").getX509Certificates(cryptoType));
357             callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
358             callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
359             callbackHandler.setIssuer("www.example.com");
360 
361             SAMLCallback samlCallback = new SAMLCallback();
362             SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
363             SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback);
364 
365             Crypto issuerCrypto = CryptoFactory.getInstance("saml/samlissuer.properties");
366             samlAssertion.signAssertion("samlissuer", "default", issuerCrypto, false);
367 
368             Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
369             WSSecHeader secHeader = new WSSecHeader(doc);
370             Node assertionNode = samlAssertion.toDOM(doc);
371             secHeader.insertSecurityHeader();
372             secHeader.getSecurityHeaderElement().appendChild(assertionNode);
373 
374             // Encrypt the SOAP body
375             WSSecEncrypt builder = new WSSecEncrypt(secHeader);
376             builder.setUserInfo("receiver");
377             builder.setSymmetricEncAlgorithm(WSConstants.TRIPLE_DES);
378             builder.setKeyIdentifierType(WSConstants.CUSTOM_KEY_IDENTIFIER);
379             builder.setCustomEKTokenValueType(WSConstants.WSS_SAML_KI_VALUE_TYPE);
380             builder.setCustomEKTokenId(samlAssertion.getId());
381 
382             Crypto userCrypto = CryptoFactory.getInstance("receiver-crypto.properties");
383             KeyGenerator keyGen = KeyUtils.getKeyGenerator(WSConstants.TRIPLE_DES);
384             SecretKey symmetricKey = keyGen.generateKey();
385             builder.prepare(userCrypto, symmetricKey);
386 
387             List<WSEncryptionPart> parts = new ArrayList<>();
388             WSEncryptionPart encP =
389                     new WSEncryptionPart(
390                             "add", "http://ws.apache.org/counter/counter_port_type", "Element"
391                     );
392             parts.add(encP);
393             Element refElement = builder.encryptForRef(null, parts, symmetricKey);
394             builder.addInternalRefElement(refElement);
395             builder.appendToHeader();
396 
397             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
398             transformer.transform(new DOMSource(doc), new StreamResult(baos));
399         }
400 
401         //done signature; now test sig-verification:
402         {
403             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
404             securityProperties.setValidateSamlSubjectConfirmation(false);
405             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
406             securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
407             CallbackHandlerImpl callbackHandler = new CallbackHandlerImpl();
408             securityProperties.setCallbackHandler(callbackHandler);
409 
410             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
411 
412             WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
413                     WSSecurityEventConstants.AlgorithmSuite,
414                     WSSecurityEventConstants.AlgorithmSuite,
415                     WSSecurityEventConstants.AlgorithmSuite,
416                     WSSecurityEventConstants.SAML_TOKEN,
417                     WSSecurityEventConstants.EncryptedElement,
418                     WSSecurityEventConstants.OPERATION,
419             };
420             final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
421             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), null, securityEventListener);
422 
423             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
424 
425             securityEventListener.compare();
426 
427             //header element must still be there
428             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
429             assertEquals(nodeList.getLength(), 1);
430         }
431     }
432 
433      @Test
434     public void testSAML1HOKEKDirectReferenceInbound() throws Exception {
435 
436          ByteArrayOutputStream baos = new ByteArrayOutputStream();
437          {
438              SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
439              //we set here the receiver's certificate just to test EncryptedKey references.
440              //in real life this wont work that way.
441              CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
442              cryptoType.setAlias("receiver");
443              callbackHandler.setCerts(CryptoFactory.getInstance("transmitter-crypto.properties").getX509Certificates(cryptoType));
444              callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
445              callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
446              callbackHandler.setIssuer("www.example.com");
447 
448              SAMLCallback samlCallback = new SAMLCallback();
449              SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
450              SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback);
451 
452              Crypto issuerCrypto = CryptoFactory.getInstance("saml/samlissuer.properties");
453              samlAssertion.signAssertion("samlissuer", "default", issuerCrypto, false);
454 
455              Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
456              WSSecHeader secHeader = new WSSecHeader(doc);
457              Node assertionNode = samlAssertion.toDOM(doc);
458              secHeader.insertSecurityHeader();
459              secHeader.getSecurityHeaderElement().appendChild(assertionNode);
460 
461              // Encrypt the SOAP body
462              WSSecEncrypt builder = new WSSecEncrypt(secHeader);
463              builder.setUserInfo("receiver");
464              builder.setSymmetricEncAlgorithm(WSConstants.TRIPLE_DES);
465              builder.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
466              builder.setCustomEKTokenValueType(WSConstants.WSS_SAML_KI_VALUE_TYPE);
467              builder.setCustomEKTokenId(samlAssertion.getId());
468 
469              Crypto userCrypto = CryptoFactory.getInstance("receiver-crypto.properties");
470              KeyGenerator keyGen = KeyUtils.getKeyGenerator(WSConstants.TRIPLE_DES);
471              SecretKey symmetricKey = keyGen.generateKey();
472              builder.prepare(userCrypto, symmetricKey);
473 
474              List<WSEncryptionPart> parts = new ArrayList<>();
475              WSEncryptionPart encP =
476                      new WSEncryptionPart(
477                              "add", "http://ws.apache.org/counter/counter_port_type", "Element"
478                      );
479              parts.add(encP);
480              Element refElement = builder.encryptForRef(null, parts, symmetricKey);
481              builder.addInternalRefElement(refElement);
482              builder.appendToHeader();
483 
484              javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
485              transformer.transform(new DOMSource(doc), new StreamResult(baos));
486          }
487 
488          //done signature; now test sig-verification:
489          {
490              WSSSecurityProperties securityProperties = new WSSSecurityProperties();
491              securityProperties.setValidateSamlSubjectConfirmation(false);
492              securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
493              securityProperties.loadDecryptionKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
494              CallbackHandlerImpl callbackHandler = new CallbackHandlerImpl();
495              securityProperties.setCallbackHandler(callbackHandler);
496 
497              InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
498 
499              WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
500                      WSSecurityEventConstants.AlgorithmSuite,
501                      WSSecurityEventConstants.AlgorithmSuite,
502                      WSSecurityEventConstants.AlgorithmSuite,
503                      WSSecurityEventConstants.SAML_TOKEN,
504                      WSSecurityEventConstants.EncryptedElement,
505                      WSSecurityEventConstants.OPERATION,
506              };
507              final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
508              XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), null, securityEventListener);
509 
510              Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
511 
512              securityEventListener.compare();
513 
514              //header element must still be there
515              NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
516              assertEquals(nodeList.getLength(), 1);
517          }
518     }
519 
520     @Test
521     public void testSAML2SVKeyIdentifierOutbound() throws Exception {
522 
523         ByteArrayOutputStream baos = new ByteArrayOutputStream();
524         {
525             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
526             List<WSSConstants.Action> actions = new ArrayList<>();
527             actions.add(WSSConstants.SAML_TOKEN_SIGNED);
528             securityProperties.setActions(actions);
529             SAMLCallbackHandlerImpl callbackHandler = new SAMLCallbackHandlerImpl();
530             callbackHandler.setSamlVersion(Version.SAML_20);
531             callbackHandler.setStatement(SAMLCallbackHandlerImpl.Statement.AUTHN);
532             callbackHandler.setConfirmationMethod(SAML2Constants.CONF_SENDER_VOUCHES);
533             callbackHandler.setIssuer("www.example.com");
534             callbackHandler.setSignAssertion(false);
535             KeyStore keyStore = KeyStore.getInstance("jks");
536             keyStore.load(this.getClass().getClassLoader().getResourceAsStream("transmitter.jks"), "default".toCharArray());
537             Merlin crypto = new Merlin();
538             crypto.setKeyStore(keyStore);
539             CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
540             cryptoType.setAlias("transmitter");
541             callbackHandler.setCerts(crypto.getX509Certificates(cryptoType));
542             securityProperties.setSamlCallbackHandler(callbackHandler);
543             securityProperties.setSignatureKeyIdentifier(WSSecurityTokenConstants.KeyIdentifier_X509KeyIdentifier);
544             securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
545             securityProperties.setSignatureUser("transmitter");
546             securityProperties.setCallbackHandler(new CallbackHandlerImpl());
547 
548             OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
549             XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
550             XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
551             XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
552             xmlStreamWriter.close();
553 
554             Document document = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
555             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
556             assertEquals(nodeList.getLength(), 1);
557             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
558 
559             nodeList = document.getElementsByTagNameNS("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "KeyIdentifier");
560             assertEquals(nodeList.getLength(), 2);
561             assertEquals(((Element) nodeList.item(0)).getAttributeNS(null, "ValueType"), "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLID");
562             assertEquals(((Element) nodeList.item(1)).getAttributeNS(null, "ValueType"), "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3");
563         }
564 
565         //done signature; now test sig-verification:
566         {
567             String action = WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.SAML_TOKEN_UNSIGNED;
568             Properties properties = new Properties();
569             doInboundSecurityWithWSS4J_1(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action, properties, false);
570         }
571     }
572 
573     @Test
574     public void testSAML2SVKeyIdentifierInbound() throws Exception {
575 
576         ByteArrayOutputStream baos = new ByteArrayOutputStream();
577         {
578             SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
579             callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
580             callbackHandler.setConfirmationMethod(SAML2Constants.CONF_SENDER_VOUCHES);
581             callbackHandler.setIssuer("www.example.com");
582             callbackHandler.setSignAssertion(false);
583 
584             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
585             String action = WSHandlerConstants.SAML_TOKEN_SIGNED;
586             Properties properties = new Properties();
587             properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
588             properties.setProperty(WSHandlerConstants.SIG_KEY_ID, "X509KeyIdentifier");
589             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
590 
591             //some test that we can really sure we get what we want from WSS4J
592             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
593             assertEquals(nodeList.getLength(), 1);
594             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
595 
596             nodeList = securedDocument.getElementsByTagNameNS("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "KeyIdentifier");
597             assertEquals(nodeList.getLength(), 2);
598             assertEquals(((Element) nodeList.item(0)).getAttributeNS(null, "ValueType"), "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLID");
599             assertEquals(((Element) nodeList.item(1)).getAttributeNS(null, "ValueType"), "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-x509-token-profile-1.0#X509v3");
600 
601             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
602             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
603         }
604 
605         //done signature; now test sig-verification:
606         {
607             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
608             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
609             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
610 
611             WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
612                     WSSecurityEventConstants.AlgorithmSuite,
613                     WSSecurityEventConstants.AlgorithmSuite,
614                     WSSecurityEventConstants.AlgorithmSuite,
615                     WSSecurityEventConstants.AlgorithmSuite,
616                     WSSecurityEventConstants.AlgorithmSuite,
617                     WSSecurityEventConstants.AlgorithmSuite,
618                     WSSecurityEventConstants.SAML_TOKEN,
619                     WSSecurityEventConstants.X509Token,
620                     WSSecurityEventConstants.SignatureValue,
621                     WSSecurityEventConstants.SignedElement,
622                     WSSecurityEventConstants.SIGNED_PART,
623                     WSSecurityEventConstants.OPERATION,
624             };
625             final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
626             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), null, securityEventListener);
627 
628             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
629 
630             securityEventListener.compare();
631 
632             //header element must still be there
633             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
634             assertEquals(nodeList.getLength(), 1);
635         }
636     }
637 
638     @Test
639     public void testSAML2HOKKeyIdentifierOutbound() throws Exception {
640 
641         ByteArrayOutputStream baos = new ByteArrayOutputStream();
642         {
643             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
644             List<WSSConstants.Action> actions = new ArrayList<>();
645             actions.add(WSSConstants.SAML_TOKEN_SIGNED);
646             securityProperties.setActions(actions);
647             SAMLCallbackHandlerImpl callbackHandler = new SAMLCallbackHandlerImpl();
648             callbackHandler.setSamlVersion(Version.SAML_20);
649             callbackHandler.setStatement(SAMLCallbackHandlerImpl.Statement.AUTHN);
650             callbackHandler.setConfirmationMethod(SAML2Constants.CONF_HOLDER_KEY);
651             callbackHandler.setIssuer("www.example.com");
652             KeyStore keyStore = KeyStore.getInstance("jks");
653             keyStore.load(this.getClass().getClassLoader().getResourceAsStream("transmitter.jks"), "default".toCharArray());
654             Merlin crypto = new Merlin();
655             crypto.setKeyStore(keyStore);
656             CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
657             cryptoType.setAlias("transmitter");
658             callbackHandler.setCerts(crypto.getX509Certificates(cryptoType));
659             securityProperties.setSamlCallbackHandler(callbackHandler);
660             securityProperties.setSignatureKeyIdentifier(WSSecurityTokenConstants.KEYIDENTIFIER_EMBEDDED_KEY_IDENTIFIER_REF);
661             securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
662             securityProperties.setSignatureUser("transmitter");
663             securityProperties.setCallbackHandler(new CallbackHandlerImpl());
664 
665             OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
666             XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
667             XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
668             XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
669             xmlStreamWriter.close();
670 
671             Document document = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
672             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
673             assertEquals(nodeList.getLength(), 2);
674             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_SAML_ASSERTION.getLocalPart());
675             assertEquals(nodeList.item(1).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
676 
677             nodeList = document.getElementsByTagNameNS("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "KeyIdentifier");
678             assertEquals(nodeList.getLength(), 1);
679             assertEquals(((Element) nodeList.item(0)).getAttributeNS(null, "ValueType"), "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLID");
680         }
681 
682         //done signature; now test sig-verification:
683         {
684             String action = WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.SAML_TOKEN_SIGNED;
685             Properties properties = new Properties();
686             doInboundSecurityWithWSS4J_1(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action, properties, false);
687         }
688     }
689 
690     @Test
691     public void testSAML2HOKKeyIdentifierInbound() throws Exception {
692 
693         ByteArrayOutputStream baos = new ByteArrayOutputStream();
694         {
695             SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
696             callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
697             callbackHandler.setConfirmationMethod(SAML2Constants.CONF_HOLDER_KEY);
698             callbackHandler.setIssuer("www.example.com");
699 
700             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
701             String action = WSHandlerConstants.SAML_TOKEN_SIGNED;
702             Properties properties = new Properties();
703             properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
704             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
705 
706             //some test that we can really sure we get what we want from WSS4J
707             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
708             assertEquals(nodeList.getLength(), 2);
709             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_SAML_ASSERTION.getLocalPart());
710             assertEquals(nodeList.item(1).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
711 
712             nodeList = securedDocument.getElementsByTagNameNS("http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "KeyIdentifier");
713             assertEquals(nodeList.getLength(), 1);
714             assertEquals(((Element) nodeList.item(0)).getAttributeNS(null, "ValueType"), "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLID");
715 
716             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
717             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
718         }
719 
720         //done signature; now test sig-verification:
721         {
722             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
723             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
724             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
725 
726             WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
727                     WSSecurityEventConstants.AlgorithmSuite,
728                     WSSecurityEventConstants.AlgorithmSuite,
729                     WSSecurityEventConstants.AlgorithmSuite,
730                     WSSecurityEventConstants.AlgorithmSuite,
731                     WSSecurityEventConstants.AlgorithmSuite,
732                     WSSecurityEventConstants.SAML_TOKEN,
733                     WSSecurityEventConstants.SignatureValue,
734                     WSSecurityEventConstants.SIGNED_PART,
735                     WSSecurityEventConstants.OPERATION,
736             };
737             final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
738             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), null, securityEventListener);
739 
740             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
741 
742             securityEventListener.compare();
743 
744             //header element must still be there
745             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
746             assertEquals(nodeList.getLength(), 2);
747             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_SAML_ASSERTION.getLocalPart());
748             assertEquals(nodeList.item(1).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
749         }
750     }
751 
752     /* not implemented!
753     @Test
754     public void testSAML2HOKDirectReferenceOutbound() throws Exception {
755 
756         ByteArrayOutputStream baos = new ByteArrayOutputStream();
757         {
758             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
759             WSSConstants.Action[] actions = new WSSConstants.Action[]{WSSConstants.SAML_TOKEN_SIGNED};
760             securityProperties.setActions(actions);
761             SAMLCallbackHandlerImpl callbackHandler = new SAMLCallbackHandlerImpl();
762             callbackHandler.setSamlVersion(Version.SAML_20);
763             callbackHandler.setStatement(SAMLCallbackHandlerImpl.Statement.AUTHN);
764             callbackHandler.setConfirmationMethod(SAML2Constants.CONF_HOLDER_KEY);
765             callbackHandler.setIssuer("www.example.com");
766             KeyStore keyStore = KeyStore.getInstance("jks");
767             keyStore.load(this.getClass().getClassLoader().getResourceAsStream("transmitter.jks"), "default".toCharArray());
768             Merlin crypto = new Merlin();
769             crypto.setKeyStore(keyStore);
770             callbackHandler.setCerts(crypto.getCertificates("transmitter"));
771             securityProperties.setSamlCallbackHandler(callbackHandler);
772             securityProperties.setSignatureKeyIdentifierType(WSSConstants.WSSKeyIdentifierType.SECURITY_TOKEN_DIRECT_REFERENCE);
773             securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
774             securityProperties.setSignatureUser("transmitter");
775              securityProperties.setCallbackHandler(new CallbackHandlerImpl());
776 
777             OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
778             XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
779             XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
780             XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
781             xmlStreamWriter.close();
782 
783             Document document = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
784             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
785             assertEquals(nodeList.getLength(), 2);
786         }
787 
788         //done signature; now test sig-verification:
789         {
790             String action = WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.SAML_TOKEN_SIGNED;
791             Properties properties = new Properties();
792             properties.setProperty(WSHandlerConstants.IS_BSP_COMPLIANT, "true");
793             doInboundSecurityWithWSS4J_1(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action, SOAPConstants.SOAP_1_1_PROTOCOL, properties, false);
794         }
795     }
796     */
797 
798     @Test
799     public void testSAML2HOKDirectReferenceInbound() throws Exception {
800 
801         ByteArrayOutputStream baos = new ByteArrayOutputStream();
802         {
803             SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
804             callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
805             callbackHandler.setConfirmationMethod(SAML2Constants.CONF_HOLDER_KEY);
806             callbackHandler.setIssuer("www.example.com");
807 
808             SAMLCallback samlCallback = new SAMLCallback();
809             SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
810             SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback);
811 
812             Crypto issuerCrypto = CryptoFactory.getInstance("saml/samlissuer.properties");
813             samlAssertion.signAssertion("samlissuer", "default", issuerCrypto, false);
814 
815             Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
816             WSSecHeader secHeader = new WSSecHeader(doc);
817             secHeader.insertSecurityHeader();
818 
819             WSSecSignatureSAML wsSign = new WSSecSignatureSAML(secHeader);
820             wsSign.setUserInfo("transmitter", "default");
821             wsSign.setUseDirectReferenceToAssertion(true);
822             wsSign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
823 
824             Crypto userCrypto = CryptoFactory.getInstance("transmitter-crypto.properties");
825             Document securedDocument = wsSign.build(userCrypto, samlAssertion, null, null, null);
826 
827             //some test that we can really sure we get what we want from WSS4J
828             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
829             assertEquals(nodeList.getLength(), 2);
830             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_SAML_ASSERTION.getLocalPart());
831             assertEquals(nodeList.item(1).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
832 
833             nodeList = securedDocument.getElementsByTagNameNS(
834                     "http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd", "SecurityTokenReference");
835             assertEquals(nodeList.getLength(), 1);
836             assertEquals(
837                     ((Element) nodeList.item(0)).
838                             getAttributeNS("http://docs.oasis-open.org/wss/oasis-wss-wssecurity-secext-1.1.xsd", "TokenType"),
839                     "http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.1#SAMLV2.0");
840 
841             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
842             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
843         }
844 
845         //done signature; now test sig-verification:
846         {
847             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
848             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
849             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
850 
851             WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
852                     WSSecurityEventConstants.AlgorithmSuite,
853                     WSSecurityEventConstants.AlgorithmSuite,
854                     WSSecurityEventConstants.AlgorithmSuite,
855                     WSSecurityEventConstants.AlgorithmSuite,
856                     WSSecurityEventConstants.AlgorithmSuite,
857                     WSSecurityEventConstants.SAML_TOKEN,
858                     WSSecurityEventConstants.SignatureValue,
859                     WSSecurityEventConstants.SIGNED_PART,
860                     WSSecurityEventConstants.OPERATION,
861             };
862             final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
863             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), null, securityEventListener);
864 
865             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
866 
867             securityEventListener.compare();
868 
869             //header element must still be there
870             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
871             assertEquals(nodeList.getLength(), 2);
872         }
873     }
874 }