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;
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.nio.file.Path;
26  import java.time.ZoneOffset;
27  import java.time.ZonedDateTime;
28  import java.util.ArrayList;
29  import java.util.HashMap;
30  import java.util.List;
31  import java.util.Map;
32  import java.util.Properties;
33  
34  import javax.xml.stream.XMLStreamException;
35  import javax.xml.stream.XMLStreamReader;
36  import javax.xml.stream.XMLStreamWriter;
37  import javax.xml.transform.dom.DOMSource;
38  import javax.xml.transform.stream.StreamResult;
39  
40  import org.apache.wss4j.common.ConfigurationConstants;
41  import org.apache.wss4j.common.cache.EHCacheReplayCache;
42  import org.apache.wss4j.common.cache.ReplayCache;
43  import org.apache.wss4j.common.ext.WSSecurityException;
44  import org.apache.wss4j.common.util.DateUtil;
45  import org.apache.wss4j.common.util.UsernameTokenUtil;
46  import org.apache.wss4j.dom.WSConstants;
47  import org.apache.wss4j.dom.handler.WSHandlerConstants;
48  import org.apache.wss4j.stax.ext.WSSConstants;
49  import org.apache.wss4j.stax.ext.WSSSecurityProperties;
50  import org.apache.wss4j.stax.securityEvent.UsernameTokenSecurityEvent;
51  import org.apache.wss4j.stax.securityEvent.WSSecurityEventConstants;
52  import org.apache.wss4j.stax.setup.ConfigurationConverter;
53  import org.apache.wss4j.stax.setup.InboundWSSec;
54  import org.apache.wss4j.stax.setup.OutboundWSSec;
55  import org.apache.wss4j.stax.setup.WSSec;
56  import org.apache.wss4j.stax.test.utils.StAX2DOM;
57  import org.apache.wss4j.stax.test.utils.XmlReaderToWriter;
58  import org.apache.xml.security.exceptions.XMLSecurityException;
59  import org.apache.xml.security.stax.securityEvent.SecurityEvent;
60  import org.apache.xml.security.stax.securityEvent.SecurityEventListener;
61  import org.apache.xml.security.utils.XMLUtils;
62  import org.junit.jupiter.api.Test;
63  import org.junit.jupiter.api.io.TempDir;
64  import org.junit.jupiter.params.ParameterizedTest;
65  import org.junit.jupiter.params.provider.ValueSource;
66  import org.w3c.dom.Document;
67  import org.w3c.dom.Element;
68  import org.w3c.dom.NodeList;
69  
70  import static org.junit.jupiter.api.Assertions.assertEquals;
71  import static org.junit.jupiter.api.Assertions.assertNotNull;
72  import static org.junit.jupiter.api.Assertions.assertTrue;
73  import static org.junit.jupiter.api.Assertions.fail;
74  
75  public class UsernameTokenTest extends AbstractTestBase {
76  
77      @Test
78      public void testDefaultConfigurationInbound() throws Exception {
79          ByteArrayOutputStream baos = new ByteArrayOutputStream();
80          {
81              InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
82              String action = WSHandlerConstants.USERNAME_TOKEN;
83              Properties properties = new Properties();
84              Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
85  
86              //some test that we can really sure we get what we want from WSS4J
87              NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSSE_USERNAME_TOKEN.getNamespaceURI(), WSSConstants.TAG_WSSE_USERNAME_TOKEN.getLocalPart());
88              assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
89  
90              nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSSE_PASSWORD.getNamespaceURI(), WSSConstants.TAG_WSSE_PASSWORD.getLocalPart());
91              assertEquals(nodeList.getLength(), 1);
92              assertEquals(((Element) nodeList.item(0)).getAttributeNS(null, WSSConstants.ATT_NULL_Type.getLocalPart()), WSSConstants.UsernameTokenPasswordType.PASSWORD_DIGEST.getNamespace());
93  
94              javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
95              transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
96          }
97  
98          //done UsernameToken; now verification:
99          {
100             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
101             securityProperties.setCallbackHandler(new CallbackHandlerImpl());
102             //securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
103             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
104 
105             WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
106                     WSSecurityEventConstants.USERNAME_TOKEN,
107                     WSSecurityEventConstants.OPERATION,
108             };
109             final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
110             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), null, securityEventListener);
111 
112             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
113 
114             securityEventListener.compare();
115 
116             //header element must still be there
117             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSSE_USERNAME_TOKEN.getNamespaceURI(), WSSConstants.TAG_WSSE_USERNAME_TOKEN.getLocalPart());
118             assertEquals(nodeList.getLength(), 1);
119             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
120         }
121     }
122 
123     @Test
124     public void testWrongUsername() throws Exception {
125         ByteArrayOutputStream baos = new ByteArrayOutputStream();
126         {
127             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
128             String action = WSHandlerConstants.USERNAME_TOKEN;
129             Properties properties = new Properties();
130             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
131 
132             //some test that we can really sure we get what we want from WSS4J
133             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSSE_USERNAME_TOKEN.getNamespaceURI(), WSSConstants.TAG_WSSE_USERNAME_TOKEN.getLocalPart());
134             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
135 
136             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
137             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
138         }
139 
140         //done UsernameToken; now verification:
141         {
142             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
143             securityProperties.setCallbackHandler(new CallbackHandlerImpl("wrongUsername"));
144             //securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
145             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties, false, true);
146             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
147 
148             try {
149                 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
150                 fail("Expected XMLStreamException");
151             } catch (XMLStreamException e) {
152                 assertNotNull(e.getCause());
153                 assertTrue(e.getCause() instanceof WSSecurityException);
154                 assertEquals(e.getCause().getMessage(), "The security token could not be authenticated or authorized");
155                 assertEquals(((WSSecurityException) e.getCause()).getFaultCode(), WSSecurityException.FAILED_AUTHENTICATION);
156             }
157         }
158     }
159 
160     //Username can't be checked in swssf, it must be done via SecurityEvent
161     @Test
162     public void testInboundPW_TEXT() throws Exception {
163         ByteArrayOutputStream baos = new ByteArrayOutputStream();
164         {
165             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
166             String action = WSHandlerConstants.USERNAME_TOKEN;
167             Properties properties = new Properties();
168             properties.setProperty(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
169             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
170 
171             //some test that we can really sure we get what we want from WSS4J
172             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSSE_USERNAME_TOKEN.getNamespaceURI(), WSSConstants.TAG_WSSE_USERNAME_TOKEN.getLocalPart());
173             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
174 
175             nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSSE_PASSWORD.getNamespaceURI(), WSSConstants.TAG_WSSE_PASSWORD.getLocalPart());
176             assertEquals(nodeList.getLength(), 1);
177             assertEquals(((Element) nodeList.item(0)).getAttributeNS(null, WSSConstants.ATT_NULL_Type.getLocalPart()), WSSConstants.UsernameTokenPasswordType.PASSWORD_TEXT.getNamespace());
178 
179             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
180             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
181         }
182 
183         //done UsernameToken; now verification:
184         {
185             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
186             securityProperties.setCallbackHandler(new CallbackHandlerImpl("username"));
187             //securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
188             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties, false, true);
189 
190             SecurityEventListener securityEventListener = new SecurityEventListener() {
191                 @Override
192                 public void registerSecurityEvent(SecurityEvent securityEvent) throws WSSecurityException {
193                     if (securityEvent instanceof UsernameTokenSecurityEvent) {
194                         UsernameTokenSecurityEvent usernameTokenSecurityEvent = (UsernameTokenSecurityEvent) securityEvent;
195                         if (!"username".equals(usernameTokenSecurityEvent.getSecurityToken().getPrincipal().getName())) {
196                             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "empty",
197                                                           new Object[] {"Wrong username"});
198                         }
199                     }
200                 }
201             };
202 
203             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), new ArrayList<SecurityEvent>(), securityEventListener);
204 
205             try {
206                 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
207                 fail("Expected XMLStreamException");
208             } catch (XMLStreamException e) {
209                 assertEquals(((WSSecurityException) e.getCause()).getFaultCode(), WSSecurityException.FAILED_AUTHENTICATION);
210             }
211         }
212     }
213 
214     //wss4j bug. PWNONE throws an NPE...
215     /*@Test
216     public void testInboundPWNONE() throws Exception {
217         ByteArrayOutputStream baos = new ByteArrayOutputStream();
218         {
219             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
220             String action = WSHandlerConstants.USERNAME_TOKEN;
221             Properties properties = new Properties();
222             properties.setProperty(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_NONE);
223             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
224 
225             //some test that we can really sure we get what we want from WSS4J
226             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSSE_USERNAME_TOKEN.getNamespaceURI(), WSSConstants.TAG_WSSE_USERNAME_TOKEN.getLocalPart());
227             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
228 
229             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
230             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
231         }
232 
233         //done UsernameToken; now verification:
234         {
235             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
236             securityProperties.setCallbackHandler(new CallbackHandlerImpl());
237             //securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
238             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
239             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
240 
241             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
242 
243             //header element must still be there
244             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSSE_USERNAME_TOKEN.getNamespaceURI(), WSSConstants.TAG_WSSE_USERNAME_TOKEN.getLocalPart());
245             assertEquals(nodeList.getLength(), 1);
246             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
247         }
248     }
249     */
250 
251     @Test
252     public void testReusedNonce(@TempDir Path tempDir) throws Exception {
253 
254         ZonedDateTime created = ZonedDateTime.now(ZoneOffset.UTC);
255         String createdString = DateUtil.getDateTimeFormatter(true).format(created);
256         String digest =
257             UsernameTokenUtil.doPasswordDigest(
258                 XMLUtils.decode("Ex2YESUvsa1qne1m6TM8XA=="), createdString, "default"
259             );
260 
261         String req = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
262                 "<env:Envelope xmlns:env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
263                 "    <env:Header>" +
264                 "       <wsse:Security xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" env:mustUnderstand=\"1\">" +
265                 "           <wsse:UsernameToken wsu:Id=\"UsernameToken-1\">" +
266                 "               <wsse:Username>transmitter</wsse:Username>" +
267                 "               <wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest\">" + digest + "</wsse:Password>" +
268                 "               <wsse:Nonce EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\">Ex2YESUvsa1qne1m6TM8XA==</wsse:Nonce>" +
269                 "               <wsu:Created>" + createdString + "</wsu:Created>" +
270                 "           </wsse:UsernameToken>" +
271                 "       </wsse:Security>\n" +
272                 "    </env:Header>\n" +
273                 "    <env:Body>\n" +
274                 "    </env:Body>\n" +
275                 "</env:Envelope>";
276 
277         WSSSecurityProperties securityProperties = new WSSSecurityProperties();
278         securityProperties.setCallbackHandler(new CallbackHandlerImpl());
279         ReplayCache replayCache = createCache("wss4j.nonce.cache", tempDir);
280         securityProperties.setNonceReplayCache(replayCache);
281         InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties, false, true);
282         XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(req.getBytes())));
283         StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
284 
285         try {
286             xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(req.getBytes())));
287             StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
288             fail("Expected XMLStreamException");
289         } catch (XMLStreamException e) {
290             assertEquals(((WSSecurityException) e.getCause()).getFaultCode(), WSSecurityException.FAILED_AUTHENTICATION);
291         }
292 
293         replayCache.close();
294     }
295 
296     /**
297      * This is a test for processing an "old" UsernameToken, i.e. one with a "Created" element that is
298      * out of date
299      */
300     @Test
301     public void testOldUsernameToken() throws Exception {
302 
303         ZonedDateTime created = ZonedDateTime.now(ZoneOffset.UTC).minusSeconds(301L);
304         String createdString = DateUtil.getDateTimeFormatter(true).format(created);
305 
306         String digest =
307             UsernameTokenUtil.doPasswordDigest(
308                 XMLUtils.decode("Ex2YEKVvsa1qne1m6TM8XA=="), createdString, "default"
309             );
310 
311         String req = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
312                 "<env:Envelope xmlns:env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
313                 "    <env:Header>" +
314                 "       <wsse:Security xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" env:mustUnderstand=\"1\">" +
315                 "           <wsse:UsernameToken wsu:Id=\"UsernameToken-1\">" +
316                 "               <wsse:Username>transmitter</wsse:Username>" +
317                 "               <wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest\">" + digest + "</wsse:Password>" +
318                 "               <wsse:Nonce EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\">Ex2YEKVvsa1qne1m6TM8XA==</wsse:Nonce>" +
319                 "               <wsu:Created>" + createdString + "</wsu:Created>" +
320                 "           </wsse:UsernameToken>" +
321                 "       </wsse:Security>\n" +
322                 "    </env:Header>\n" +
323                 "    <env:Body>\n" +
324                 "    </env:Body>\n" +
325                 "</env:Envelope>";
326 
327         WSSSecurityProperties securityProperties = new WSSSecurityProperties();
328         securityProperties.setCallbackHandler(new CallbackHandlerImpl());
329         InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties, false, true);
330 
331         try {
332             XMLStreamReader xmlStreamReader =
333                 wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(req.getBytes())));
334             StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
335             fail("Expected XMLStreamException");
336         } catch (XMLStreamException e) {
337             assertEquals(((WSSecurityException) e.getCause()).getFaultCode(), WSSecurityException.MESSAGE_EXPIRED);
338         }
339     }
340 
341     /**
342      * This is a test for processing a UsernameToken where the "Created" element is in the (near)
343      * future. It should be accepted by default when it is created 30 seconds in the future.
344      */
345     @Test
346     public void testNearFutureCreated() throws Exception {
347         ZonedDateTime created = ZonedDateTime.now(ZoneOffset.UTC).plusSeconds(30L);
348         String createdString = DateUtil.getDateTimeFormatter(true).format(created);
349 
350         String digest =
351             UsernameTokenUtil.doPasswordDigest(
352                 XMLUtils.decode("Ex2YEKVvSa1qne1m6TM8XA=="), createdString, "default"
353             );
354 
355         String req = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
356                 "<env:Envelope xmlns:env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
357                 "    <env:Header>" +
358                 "       <wsse:Security xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" env:mustUnderstand=\"1\">" +
359                 "           <wsse:UsernameToken wsu:Id=\"UsernameToken-1\">" +
360                 "               <wsse:Username>transmitter</wsse:Username>" +
361                 "               <wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest\">" + digest + "</wsse:Password>" +
362                 "               <wsse:Nonce EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\">Ex2YEKVvSa1qne1m6TM8XA==</wsse:Nonce>" +
363                 "               <wsu:Created>" + createdString + "</wsu:Created>" +
364                 "           </wsse:UsernameToken>" +
365                 "       </wsse:Security>\n" +
366                 "    </env:Header>\n" +
367                 "    <env:Body>\n" +
368                 "    </env:Body>\n" +
369                 "</env:Envelope>";
370 
371         WSSSecurityProperties securityProperties = new WSSSecurityProperties();
372         securityProperties.setCallbackHandler(new CallbackHandlerImpl());
373         InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
374         XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(req.getBytes())));
375         StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
376     }
377 
378     /**
379      * This is a test for processing a UsernameToken where the "Created" element is in the future.
380      * A UsernameToken that is 120 seconds in the future should be rejected by default.
381      */
382     @Test
383     public void testFutureCreated() throws Exception {
384         ZonedDateTime created = ZonedDateTime.now(ZoneOffset.UTC).plusSeconds(120L);
385         String createdString = DateUtil.getDateTimeFormatter(true).format(created);
386 
387         String digest =
388             UsernameTokenUtil.doPasswordDigest(
389                 XMLUtils.decode("Ex2YEKVvsa1Qne1m6TM8XA=="), createdString, "default"
390             );
391 
392         String req = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>" +
393                 "<env:Envelope xmlns:env=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
394                 "    <env:Header>" +
395                 "       <wsse:Security xmlns:wsse=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd\" xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" env:mustUnderstand=\"1\">" +
396                 "           <wsse:UsernameToken wsu:Id=\"UsernameToken-1\">" +
397                 "               <wsse:Username>transmitter</wsse:Username>" +
398                 "               <wsse:Password Type=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordDigest\">" + digest + "</wsse:Password>" +
399                 "               <wsse:Nonce EncodingType=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-soap-message-security-1.0#Base64Binary\">Ex2YEKVvsa1Qne1m6TM8XA==</wsse:Nonce>" +
400                 "               <wsu:Created>" + createdString + "</wsu:Created>" +
401                 "           </wsse:UsernameToken>" +
402                 "       </wsse:Security>\n" +
403                 "    </env:Header>\n" +
404                 "    <env:Body>\n" +
405                 "    </env:Body>\n" +
406                 "</env:Envelope>";
407 
408         WSSSecurityProperties securityProperties = new WSSSecurityProperties();
409         securityProperties.setCallbackHandler(new CallbackHandlerImpl());
410         InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties, false, true);
411 
412         try {
413             XMLStreamReader xmlStreamReader =
414                 wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(req.getBytes())));
415             StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
416             fail("Expected XMLStreamException");
417         } catch (XMLStreamException e) {
418             assertEquals(((WSSecurityException) e.getCause()).getFaultCode(), WSSecurityException.MESSAGE_EXPIRED);
419         }
420     }
421 
422     @Test
423     public void testDefaultConfigurationOutbound() throws Exception {
424         ByteArrayOutputStream baos = new ByteArrayOutputStream();
425 
426         {
427             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
428             List<WSSConstants.Action> actions = new ArrayList<>();
429             actions.add(WSSConstants.USERNAMETOKEN);
430             securityProperties.setActions(actions);
431             securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
432             securityProperties.setTokenUser("transmitter");
433             securityProperties.setCallbackHandler(new CallbackHandlerImpl());
434 
435             OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
436             XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
437             XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
438             XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
439             xmlStreamWriter.close();
440 
441             Document document = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
442             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSSE_USERNAME_TOKEN.getNamespaceURI(), WSSConstants.TAG_WSSE_USERNAME_TOKEN.getLocalPart());
443             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
444 
445             nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSSE_PASSWORD.getNamespaceURI(), WSSConstants.TAG_WSSE_PASSWORD.getLocalPart());
446             assertEquals(nodeList.getLength(), 1);
447             assertEquals(((Element) nodeList.item(0)).getAttributeNS(null, WSSConstants.ATT_NULL_Type.getLocalPart()), WSSConstants.UsernameTokenPasswordType.PASSWORD_DIGEST.getNamespace());
448         }
449 
450         //done UsernameToken; now verification:
451         {
452             String action = WSHandlerConstants.USERNAME_TOKEN;
453             doInboundSecurityWithWSS4J(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action);
454         }
455     }
456 
457     @Test
458     public void testOutboundPW_NONE() throws Exception {
459         ByteArrayOutputStream baos = new ByteArrayOutputStream();
460 
461         {
462             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
463             List<WSSConstants.Action> actions = new ArrayList<>();
464             actions.add(WSSConstants.USERNAMETOKEN);
465             securityProperties.setActions(actions);
466             securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
467             securityProperties.setTokenUser("transmitter");
468             securityProperties.setUsernameTokenPasswordType(WSSConstants.UsernameTokenPasswordType.PASSWORD_NONE);
469             securityProperties.setCallbackHandler(new CallbackHandlerImpl());
470 
471             OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
472             XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
473             XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
474             XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
475             xmlStreamWriter.close();
476 
477             Document document = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
478             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSSE_USERNAME_TOKEN.getNamespaceURI(), WSSConstants.TAG_WSSE_USERNAME_TOKEN.getLocalPart());
479             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
480 
481             nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSSE_PASSWORD.getNamespaceURI(), WSSConstants.TAG_WSSE_PASSWORD.getLocalPart());
482             assertEquals(nodeList.getLength(), 0);
483         }
484 
485         //done UsernameToken; now verification:
486         {
487             String action = WSHandlerConstants.USERNAME_TOKEN;
488 
489             Document document = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
490             Properties properties = new Properties();
491             properties.put(WSHandlerConstants.ALLOW_USERNAMETOKEN_NOPASSWORD, "true");
492             doInboundSecurityWithWSS4J_1(document, action, properties, false);
493         }
494     }
495 
496     @Test
497     public void testOutboundPW_TEXT() throws Exception {
498         ByteArrayOutputStream baos = new ByteArrayOutputStream();
499 
500         {
501             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
502             List<WSSConstants.Action> actions = new ArrayList<>();
503             actions.add(WSSConstants.USERNAMETOKEN);
504             securityProperties.setActions(actions);
505             securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
506             securityProperties.setTokenUser("transmitter");
507             securityProperties.setUsernameTokenPasswordType(WSSConstants.UsernameTokenPasswordType.PASSWORD_TEXT);
508             securityProperties.setCallbackHandler(new CallbackHandlerImpl());
509 
510             OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
511             XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
512             XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
513             XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
514             xmlStreamWriter.close();
515 
516             Document document = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
517             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSSE_USERNAME_TOKEN.getNamespaceURI(), WSSConstants.TAG_WSSE_USERNAME_TOKEN.getLocalPart());
518             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
519 
520             nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSSE_PASSWORD.getNamespaceURI(), WSSConstants.TAG_WSSE_PASSWORD.getLocalPart());
521             assertEquals(nodeList.getLength(), 1);
522             assertEquals(((Element) nodeList.item(0)).getAttributeNS(null, WSSConstants.ATT_NULL_Type.getLocalPart()), WSSConstants.UsernameTokenPasswordType.PASSWORD_TEXT.getNamespace());
523         }
524 
525         //done UsernameToken; now verification:
526         {
527             String action = WSHandlerConstants.USERNAME_TOKEN;
528             doInboundSecurityWithWSS4J(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action);
529         }
530     }
531 
532     @ParameterizedTest
533     @ValueSource(strings = { "transmitter", "sender", "randomUsername" })
534     public void testOutboundPW_TEXT_withEmptyPassword(String transmitter) throws Exception {
535         ByteArrayOutputStream baos = new ByteArrayOutputStream();
536 
537         {
538             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
539             List<WSSConstants.Action> actions = new ArrayList<>();
540             actions.add(WSSConstants.USERNAMETOKEN);
541             securityProperties.setActions(actions);
542             securityProperties.setTokenUser(transmitter);
543             securityProperties.setUsernameTokenPasswordType(WSSConstants.UsernameTokenPasswordType.PASSWORD_TEXT);
544             securityProperties.setCallbackHandler(x -> {});
545 
546             try {
547                 OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
548                 XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
549                 XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
550                 XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
551                 xmlStreamWriter.close();
552                 fail("Expecting an XMLStreamException");
553             } catch (XMLStreamException e) {
554                 assertNotNull(e.getCause());
555                 assertTrue(WSSecurityException.class.isAssignableFrom(e.getCause().getClass()), "Cause should be a WSSecurityException");
556                 WSSecurityException root = (WSSecurityException)e.getCause();
557                 assertEquals(root.getErrorCode(), WSSecurityException.ErrorCode.FAILURE);
558                 assertEquals("noPassword", root.getMsgID());
559                 assertTrue(root.getMessage().contains(transmitter), () -> "Message string: <" + root.getMessage() + "> to include <" + transmitter + '>');
560             }
561         }
562     }
563 
564     @Test
565     public void testOutboundSign() throws Exception {
566         ByteArrayOutputStream baos = new ByteArrayOutputStream();
567 
568         {
569             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
570             List<WSSConstants.Action> actions = new ArrayList<>();
571             actions.add(WSSConstants.USERNAMETOKEN_SIGNED);
572             securityProperties.setActions(actions);
573             securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
574             securityProperties.setTokenUser("transmitter");
575             securityProperties.setCallbackHandler(new CallbackHandlerImpl());
576 
577             OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
578             XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
579             XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
580             XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
581             xmlStreamWriter.close();
582 
583             Document document = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
584             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
585             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
586 
587             nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSSE_USERNAME_TOKEN.getNamespaceURI(), WSSConstants.TAG_WSSE_USERNAME_TOKEN.getLocalPart());
588             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
589 
590             nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSSE_PASSWORD.getNamespaceURI(), WSSConstants.TAG_WSSE_PASSWORD.getLocalPart());
591             assertEquals(nodeList.getLength(), 0);
592 
593             nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Reference.getNamespaceURI(), WSSConstants.TAG_dsig_Reference.getLocalPart());
594             assertEquals(nodeList.getLength(), 1);
595 
596             nodeList = document.getElementsByTagNameNS(WSSConstants.NS_SOAP11, WSSConstants.TAG_SOAP_BODY_LN);
597             assertEquals(nodeList.getLength(), 1);
598             String idAttrValue = ((Element) nodeList.item(0)).getAttributeNS(WSSConstants.ATT_WSU_ID.getNamespaceURI(), WSSConstants.ATT_WSU_ID.getLocalPart());
599             assertNotNull(idAttrValue);
600             assertTrue(idAttrValue.length() > 0);
601         }
602 
603         //done UsernameToken; now verification:
604         {
605             String action = WSHandlerConstants.USERNAME_TOKEN_SIGNATURE;
606             doInboundSecurityWithWSS4J(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action);
607         }
608     }
609 
610     @Test
611     public void testInboundSign() throws Exception {
612         ByteArrayOutputStream baos = new ByteArrayOutputStream();
613         {
614             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
615             String action = WSHandlerConstants.USERNAME_TOKEN_SIGNATURE;
616             Properties properties = new Properties();
617             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
618 
619             //some test that we can really sure we get what we want from WSS4J
620             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSSE_USERNAME_TOKEN.getNamespaceURI(), WSSConstants.TAG_WSSE_USERNAME_TOKEN.getLocalPart());
621             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
622 
623             nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSSE_PASSWORD.getNamespaceURI(), WSSConstants.TAG_WSSE_PASSWORD.getLocalPart());
624             assertEquals(nodeList.getLength(), 0);
625 
626             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
627             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
628         }
629 
630         //done UsernameToken; now verification:
631         {
632             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
633             securityProperties.setCallbackHandler(new CallbackHandlerImpl());
634             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
635             securityProperties.setAllowUsernameTokenNoPassword(true);
636             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
637 
638             XMLStreamReader xmlStreamReader =
639                 wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), null);
640 
641             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
642 
643             //header element must still be there
644             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSSE_USERNAME_TOKEN.getNamespaceURI(), WSSConstants.TAG_WSSE_USERNAME_TOKEN.getLocalPart());
645             assertEquals(nodeList.getLength(), 1);
646             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
647         }
648     }
649 
650     @Test
651     public void testInboundOutboundPW_NONE() throws Exception {
652 
653         ByteArrayOutputStream baos = new ByteArrayOutputStream();
654 
655         {
656             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
657             List<WSSConstants.Action> actions = new ArrayList<>();
658             actions.add(WSSConstants.USERNAMETOKEN);
659             securityProperties.setActions(actions);
660             securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
661             securityProperties.setTokenUser("transmitter");
662             securityProperties.setUsernameTokenPasswordType(WSSConstants.UsernameTokenPasswordType.PASSWORD_NONE);
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 securedDocument = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
672             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSSE_USERNAME_TOKEN.getNamespaceURI(), WSSConstants.TAG_WSSE_USERNAME_TOKEN.getLocalPart());
673             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
674 
675             nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSSE_PASSWORD.getNamespaceURI(), WSSConstants.TAG_WSSE_PASSWORD.getLocalPart());
676             assertEquals(nodeList.getLength(), 0);
677         }
678 
679         //done UsernameToken; now verification:
680 
681         // Failure expected on no password
682         try {
683             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
684             securityProperties.setCallbackHandler(new CallbackHandlerImpl());
685             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties, false, true);
686             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
687 
688             xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
689             StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
690             fail("Expected XMLStreamException");
691         } catch (XMLStreamException e) {
692             assertEquals(((WSSecurityException) e.getCause()).getFaultCode(), WSSecurityException.FAILED_AUTHENTICATION);
693         }
694 
695         // Now set the appropriate boolean and it should pass
696         {
697             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
698             securityProperties.setAllowUsernameTokenNoPassword(true);
699             securityProperties.setCallbackHandler(new CallbackHandlerImpl());
700             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
701             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
702 
703             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
704 
705             //header element must still be there
706             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSSE_USERNAME_TOKEN.getNamespaceURI(), WSSConstants.TAG_WSSE_USERNAME_TOKEN.getLocalPart());
707             assertEquals(nodeList.getLength(), 1);
708             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
709         }
710     }
711 
712     @Test
713     public void testInboundTextNonceCreated() throws Exception {
714         ByteArrayOutputStream baos = new ByteArrayOutputStream();
715         {
716             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
717             String action = WSHandlerConstants.USERNAME_TOKEN;
718             Properties properties = new Properties();
719             properties.setProperty(WSHandlerConstants.PASSWORD_TYPE, WSConstants.PW_TEXT);
720             properties.setProperty(WSHandlerConstants.ADD_USERNAMETOKEN_NONCE, "true");
721             properties.setProperty(WSHandlerConstants.ADD_USERNAMETOKEN_CREATED, "true");
722             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
723 
724             //some test that we can really sure we get what we want from WSS4J
725             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSSE_USERNAME_TOKEN.getNamespaceURI(), WSSConstants.TAG_WSSE_USERNAME_TOKEN.getLocalPart());
726             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
727 
728             nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSSE_PASSWORD.getNamespaceURI(), WSSConstants.TAG_WSSE_PASSWORD.getLocalPart());
729             assertEquals(nodeList.getLength(), 1);
730             assertEquals(((Element) nodeList.item(0)).getAttributeNS(null, WSSConstants.ATT_NULL_Type.getLocalPart()), WSSConstants.UsernameTokenPasswordType.PASSWORD_TEXT.getNamespace());
731 
732             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
733             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
734         }
735 
736         //done UsernameToken; now verification:
737         {
738             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
739             securityProperties.setCallbackHandler(new CallbackHandlerImpl());
740             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
741 
742             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), null);
743 
744             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
745 
746             //header element must still be there
747             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSSE_USERNAME_TOKEN.getNamespaceURI(), WSSConstants.TAG_WSSE_USERNAME_TOKEN.getLocalPart());
748             assertEquals(nodeList.getLength(), 1);
749             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
750         }
751     }
752 
753     @Test
754     public void testOutboundTextNonceCreated() throws Exception {
755         ByteArrayOutputStream baos = new ByteArrayOutputStream();
756 
757         {
758             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
759             List<WSSConstants.Action> actions = new ArrayList<>();
760             actions.add(WSSConstants.USERNAMETOKEN);
761             securityProperties.setActions(actions);
762             securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
763             securityProperties.setTokenUser("transmitter");
764             securityProperties.setUsernameTokenPasswordType(WSSConstants.UsernameTokenPasswordType.PASSWORD_TEXT);
765             securityProperties.setCallbackHandler(new CallbackHandlerImpl());
766             securityProperties.setAddUsernameTokenNonce(true);
767             securityProperties.setAddUsernameTokenCreated(true);
768 
769             OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
770             XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
771             XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
772             XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
773             xmlStreamWriter.close();
774 
775             Document document = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
776             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSSE_USERNAME_TOKEN.getNamespaceURI(), WSSConstants.TAG_WSSE_USERNAME_TOKEN.getLocalPart());
777             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
778 
779             nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSSE_PASSWORD.getNamespaceURI(), WSSConstants.TAG_WSSE_PASSWORD.getLocalPart());
780             assertEquals(nodeList.getLength(), 1);
781             assertEquals(((Element) nodeList.item(0)).getAttributeNS(null, WSSConstants.ATT_NULL_Type.getLocalPart()), WSSConstants.UsernameTokenPasswordType.PASSWORD_TEXT.getNamespace());
782         }
783 
784         //done UsernameToken; now verification:
785         {
786             String action = WSHandlerConstants.USERNAME_TOKEN;
787             doInboundSecurityWithWSS4J(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action);
788         }
789     }
790 
791     @Test
792     public void testPropertiesOutbound() throws Exception {
793         ByteArrayOutputStream baos = new ByteArrayOutputStream();
794 
795         {
796             Map<String, Object> config = new HashMap<>();
797             config.put(ConfigurationConstants.ACTION, ConfigurationConstants.USERNAME_TOKEN);
798             config.put(ConfigurationConstants.USER, "transmitter");
799             config.put(ConfigurationConstants.PW_CALLBACK_REF, new CallbackHandlerImpl());
800 
801             WSSSecurityProperties securityProperties = ConfigurationConverter.convert(config);
802             OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
803             XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
804             XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
805             XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
806             xmlStreamWriter.close();
807 
808             Document document = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
809             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSSE_USERNAME_TOKEN.getNamespaceURI(), WSSConstants.TAG_WSSE_USERNAME_TOKEN.getLocalPart());
810             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
811 
812             nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSSE_PASSWORD.getNamespaceURI(), WSSConstants.TAG_WSSE_PASSWORD.getLocalPart());
813             assertEquals(nodeList.getLength(), 1);
814             assertEquals(((Element) nodeList.item(0)).getAttributeNS(null, WSSConstants.ATT_NULL_Type.getLocalPart()), WSSConstants.UsernameTokenPasswordType.PASSWORD_DIGEST.getNamespace());
815         }
816 
817         //done UsernameToken; now verification:
818         {
819             String action = WSHandlerConstants.USERNAME_TOKEN;
820             doInboundSecurityWithWSS4J(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action);
821         }
822     }
823 
824     @Test
825     public void testPropertiesInbound() throws Exception {
826         ByteArrayOutputStream baos = new ByteArrayOutputStream();
827         {
828             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
829             String action = WSHandlerConstants.USERNAME_TOKEN;
830             Properties properties = new Properties();
831             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
832 
833             //some test that we can really sure we get what we want from WSS4J
834             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSSE_USERNAME_TOKEN.getNamespaceURI(), WSSConstants.TAG_WSSE_USERNAME_TOKEN.getLocalPart());
835             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
836 
837             nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_WSSE_PASSWORD.getNamespaceURI(), WSSConstants.TAG_WSSE_PASSWORD.getLocalPart());
838             assertEquals(nodeList.getLength(), 1);
839             assertEquals(((Element) nodeList.item(0)).getAttributeNS(null, WSSConstants.ATT_NULL_Type.getLocalPart()), WSSConstants.UsernameTokenPasswordType.PASSWORD_DIGEST.getNamespace());
840 
841             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
842             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
843         }
844 
845         //done UsernameToken; now verification:
846         {
847             Map<String, Object> config = new HashMap<>();
848             config.put(ConfigurationConstants.ACTION, ConfigurationConstants.USERNAME_TOKEN);
849             config.put(ConfigurationConstants.PW_CALLBACK_REF, new CallbackHandlerImpl());
850             WSSSecurityProperties securityProperties = ConfigurationConverter.convert(config);
851             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
852 
853             WSSecurityEventConstants.Event[] expectedSecurityEvents = new WSSecurityEventConstants.Event[]{
854                     WSSecurityEventConstants.USERNAME_TOKEN,
855                     WSSecurityEventConstants.OPERATION,
856             };
857             final TestSecurityEventListener securityEventListener = new TestSecurityEventListener(expectedSecurityEvents);
858             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())), null, securityEventListener);
859 
860             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
861 
862             securityEventListener.compare();
863 
864             //header element must still be there
865             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_WSSE_USERNAME_TOKEN.getNamespaceURI(), WSSConstants.TAG_WSSE_USERNAME_TOKEN.getLocalPart());
866             assertEquals(nodeList.getLength(), 1);
867             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
868         }
869     }
870 
871     private ReplayCache createCache(String key, Path tempDir) throws WSSecurityException {
872         try {
873             return new EHCacheReplayCache(key, tempDir);
874         } catch (XMLSecurityException e) {
875             throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
876         }
877     }
878 }