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.time.Duration;
26  import java.time.Instant;
27  import java.util.ArrayList;
28  import java.util.Collections;
29  import java.util.List;
30  import java.util.Properties;
31  
32  import javax.xml.stream.XMLStreamException;
33  import javax.xml.stream.XMLStreamReader;
34  import javax.xml.stream.XMLStreamWriter;
35  import javax.xml.transform.dom.DOMSource;
36  import javax.xml.transform.stream.StreamResult;
37  
38  import net.shibboleth.shared.xml.DOMTypeSupport;
39  import org.apache.wss4j.common.saml.bean.AudienceRestrictionBean;
40  import org.apache.wss4j.common.saml.bean.ConditionsBean;
41  import org.apache.wss4j.common.saml.bean.ProxyRestrictionBean;
42  import org.apache.wss4j.common.saml.builder.SAML1Constants;
43  import org.apache.wss4j.dom.handler.WSHandlerConstants;
44  import org.apache.wss4j.stax.ext.WSSConstants;
45  import org.apache.wss4j.stax.ext.WSSSecurityProperties;
46  import org.apache.wss4j.stax.setup.InboundWSSec;
47  import org.apache.wss4j.stax.setup.OutboundWSSec;
48  import org.apache.wss4j.stax.setup.WSSec;
49  import org.apache.wss4j.stax.test.AbstractTestBase;
50  import org.apache.wss4j.stax.test.CallbackHandlerImpl;
51  import org.apache.wss4j.stax.test.utils.StAX2DOM;
52  import org.apache.wss4j.stax.test.utils.XmlReaderToWriter;
53  import org.apache.xml.security.stax.securityEvent.SecurityEvent;
54  import org.junit.jupiter.api.Test;
55  import org.w3c.dom.Document;
56  import org.w3c.dom.Element;
57  import org.w3c.dom.NodeList;
58  
59  import static org.junit.jupiter.api.Assertions.assertEquals;
60  import static org.junit.jupiter.api.Assertions.assertNotNull;
61  import static org.junit.jupiter.api.Assertions.fail;
62  
63  public class SamlConditionsTest extends AbstractTestBase {
64  
65      /**
66       * Test that creates, sends and processes an unsigned SAML 1.1 authentication assertion
67       * with a custom Conditions statement.
68       */
69      @Test
70      public void testSAML1ConditionsOutbound() throws Exception {
71  
72          ByteArrayOutputStream baos = new ByteArrayOutputStream();
73          {
74              WSSSecurityProperties securityProperties = new WSSSecurityProperties();
75              List<WSSConstants.Action> actions = new ArrayList<>();
76              actions.add(WSSConstants.SAML_TOKEN_SIGNED);
77              securityProperties.setActions(actions);
78              SAMLCallbackHandlerImpl callbackHandler = new SAMLCallbackHandlerImpl();
79              callbackHandler.setStatement(SAMLCallbackHandlerImpl.Statement.AUTHN);
80              callbackHandler.setIssuer("www.example.com");
81  
82              ConditionsBean conditions = new ConditionsBean();
83              Instant notBefore = Instant.now();
84              conditions.setNotBefore(notBefore);
85              Instant notAfter = notBefore.plus(Duration.ofMinutes(20));
86              conditions.setNotAfter(notAfter);
87              callbackHandler.setConditions(conditions);
88  
89              securityProperties.setSamlCallbackHandler(callbackHandler);
90              securityProperties.loadSignatureKeyStore(this.getClass().getClassLoader().getResource("transmitter.jks"), "default".toCharArray());
91              securityProperties.setSignatureUser("transmitter");
92              securityProperties.setCallbackHandler(new CallbackHandlerImpl());
93  
94              OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
95              XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
96              XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml"));
97              XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
98              xmlStreamWriter.close();
99  
100             Document document = documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray()));
101             NodeList nodeList = document.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
102             assertEquals(nodeList.getLength(), 2);
103             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_SAML_ASSERTION.getLocalPart());
104             assertEquals(nodeList.item(1).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
105 
106             nodeList = document.getElementsByTagNameNS("urn:oasis:names:tc:SAML:1.0:assertion", "Conditions");
107             assertEquals(nodeList.getLength(), 1);
108             assertEquals(((Element) nodeList.item(0)).getAttributeNS(null, "NotBefore"), DOMTypeSupport.instantToString(notBefore));
109             assertEquals(((Element) nodeList.item(0)).getAttributeNS(null, "NotOnOrAfter"), DOMTypeSupport.instantToString(notAfter));
110         }
111 
112         //done signature; now test sig-verification:
113         {
114             String action = WSHandlerConstants.SIGNATURE + " " + WSHandlerConstants.SAML_TOKEN_SIGNED;
115             Properties properties = new Properties();
116             doInboundSecurityWithWSS4J_1(documentBuilderFactory.newDocumentBuilder().parse(new ByteArrayInputStream(baos.toByteArray())), action, properties, false);
117         }
118     }
119 
120     /**
121      * Test that creates, sends and processes an unsigned SAML 1.1 authentication assertion
122      * with a custom Conditions statement.
123      */
124     @Test
125     public void testSAML1ConditionsInbound() throws Exception {
126 
127         ByteArrayOutputStream baos = new ByteArrayOutputStream();
128         {
129             SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
130             callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
131             callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
132             callbackHandler.setIssuer("www.example.com");
133 
134             ConditionsBean conditions = new ConditionsBean();
135             Instant notBefore = Instant.now();
136             conditions.setNotBefore(notBefore);
137             Instant notAfter = notBefore.plus(Duration.ofMinutes(20));
138             conditions.setNotAfter(notAfter);
139             callbackHandler.setConditions(conditions);
140 
141             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
142             String action = WSHandlerConstants.SAML_TOKEN_SIGNED;
143             Properties properties = new Properties();
144             properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
145             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
146 
147             //some test that we can really sure we get what we want from WSS4J
148             NodeList nodeList = securedDocument.getElementsByTagNameNS(WSSConstants.TAG_dsig_Signature.getNamespaceURI(), WSSConstants.TAG_dsig_Signature.getLocalPart());
149             assertEquals(nodeList.getLength(), 2);
150             assertEquals(nodeList.item(0).getParentNode().getLocalName(), WSSConstants.TAG_SAML_ASSERTION.getLocalPart());
151             assertEquals(nodeList.item(1).getParentNode().getLocalName(), WSSConstants.TAG_WSSE_SECURITY.getLocalPart());
152 
153             nodeList = securedDocument.getElementsByTagNameNS("urn:oasis:names:tc:SAML:1.0:assertion", "Conditions");
154             assertEquals(nodeList.getLength(), 1);
155             assertEquals(((Element) nodeList.item(0)).getAttributeNS(null, "NotBefore"), DOMTypeSupport.instantToString(notBefore));
156             assertEquals(((Element) nodeList.item(0)).getAttributeNS(null, "NotOnOrAfter"), DOMTypeSupport.instantToString(notAfter));
157 
158             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
159             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
160         }
161 
162         //done signature; now test sig-verification:
163         {
164             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
165             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
166             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
167             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
168 
169             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
170             assertNotNull(document);
171         }
172     }
173 
174     /**
175      * Test that creates, sends and processes an unsigned SAML 2 authentication assertion
176      * with an (invalid) custom Conditions statement.
177      */
178     @Test
179     public void testSAML2InvalidAfterConditionsInbound() throws Exception {
180 
181         ByteArrayOutputStream baos = new ByteArrayOutputStream();
182         {
183             SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
184             callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
185             callbackHandler.setIssuer("www.example.com");
186 
187             ConditionsBean conditions = new ConditionsBean();
188             Instant notBefore = Instant.now();
189             conditions.setNotBefore(notBefore.minus(Duration.ofMinutes(5)));
190             conditions.setNotAfter(notBefore.minus(Duration.ofMinutes(3)));
191             callbackHandler.setConditions(conditions);
192 
193             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
194             String action = WSHandlerConstants.SAML_TOKEN_SIGNED;
195             Properties properties = new Properties();
196             properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
197             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
198 
199             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
200             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
201         }
202 
203         //done signature; now test sig-verification:
204         {
205             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
206             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
207             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
208             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
209 
210             try {
211                 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
212                 fail("XMLStreamException expected");
213             } catch (XMLStreamException e) {
214                 assertNotNull(e.getCause());
215             }
216         }
217     }
218 
219     @Test
220     public void testSAML2StaleNotOnOrAfter() throws Exception {
221 
222         ByteArrayOutputStream baos = new ByteArrayOutputStream();
223         {
224             SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
225             callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
226             callbackHandler.setIssuer("www.example.com");
227 
228             ConditionsBean conditions = new ConditionsBean();
229             Instant notBefore = Instant.now();
230             conditions.setNotAfter(notBefore.minus(Duration.ofMinutes(60)));
231             conditions.setNotBefore(notBefore.minus(Duration.ofMinutes(70)));
232             callbackHandler.setConditions(conditions);
233 
234             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
235             String action = WSHandlerConstants.SAML_TOKEN_SIGNED;
236             Properties properties = new Properties();
237             properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
238             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
239 
240             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
241             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
242         }
243 
244         //done signature; now test sig-verification:
245         {
246             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
247             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
248             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
249             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
250 
251             try {
252                 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
253                 fail("XMLStreamException expected");
254             } catch (XMLStreamException e) {
255                 assertNotNull(e.getCause());
256             }
257         }
258     }
259 
260     @Test
261     public void testSAML2FutureNotBefore() throws Exception {
262 
263         ByteArrayOutputStream baos = new ByteArrayOutputStream();
264         {
265             SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
266             callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
267             callbackHandler.setIssuer("www.example.com");
268 
269             ConditionsBean conditions = new ConditionsBean();
270             Instant notBefore = Instant.now();
271             conditions.setNotAfter(notBefore.plus(Duration.ofMinutes(70)));
272             conditions.setNotBefore(notBefore.plus(Duration.ofMinutes(60)));
273             callbackHandler.setConditions(conditions);
274 
275             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
276             String action = WSHandlerConstants.SAML_TOKEN_SIGNED;
277             Properties properties = new Properties();
278             properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
279             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
280 
281             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
282             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
283         }
284 
285         //done signature; now test sig-verification:
286         {
287             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
288             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
289             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
290             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
291 
292             try {
293                 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
294                 fail("XMLStreamException expected");
295             } catch (XMLStreamException e) {
296                 assertNotNull(e.getCause());
297             }
298         }
299     }
300 
301     /**
302      * Test that creates, sends and processes an unsigned SAML 2 authentication assertion
303      * with an (invalid) custom Conditions statement.
304      */
305     @Test
306     public void testSAML2InvalidBeforeConditionsInbound() throws Exception {
307 
308         ByteArrayOutputStream baos = new ByteArrayOutputStream();
309         {
310             SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
311             callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
312             callbackHandler.setIssuer("www.example.com");
313 
314             ConditionsBean conditions = new ConditionsBean();
315             Instant notBefore = Instant.now();
316             conditions.setNotBefore(notBefore.plus(Duration.ofMinutes(2)));
317             conditions.setNotAfter(notBefore.plus(Duration.ofMinutes(5)));
318             callbackHandler.setConditions(conditions);
319 
320             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
321             String action = WSHandlerConstants.SAML_TOKEN_SIGNED;
322             Properties properties = new Properties();
323             properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
324             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
325 
326             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
327             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
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             try {
338                 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
339                 fail("XMLStreamException expected");
340             } catch (XMLStreamException e) {
341                 assertNotNull(e.getCause());
342             }
343         }
344     }
345 
346     /**
347      * Test that creates, sends and processes an unsigned SAML 2 authentication assertion
348      * with a Conditions statement that has a NotBefore "in the future".
349      */
350     @Test
351     public void testSAML2FutureTTLConditions() throws Exception {
352         ByteArrayOutputStream baos = new ByteArrayOutputStream();
353         {
354             SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
355             callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
356             callbackHandler.setIssuer("www.example.com");
357 
358             ConditionsBean conditions = new ConditionsBean();
359             Instant notBefore = Instant.now();
360             conditions.setNotBefore(notBefore.plusSeconds(30));
361             conditions.setNotAfter(notBefore.plus(Duration.ofMinutes(5)));
362             callbackHandler.setConditions(conditions);
363 
364             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
365             String action = WSHandlerConstants.SAML_TOKEN_SIGNED;
366             Properties properties = new Properties();
367             properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
368             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
369 
370             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
371             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
372         }
373 
374         //done signature; now test sig-verification:
375         {
376             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
377             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
378             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
379             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
380 
381             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
382             assertNotNull(document);
383         }
384     }
385 
386     /**
387      * Test that creates, sends and processes an unsigned SAML 2 authentication assertion
388      * with a OneTimeUse Element
389      */
390     @Test
391     public void testSAML2OneTimeUse() throws Exception {
392         ByteArrayOutputStream baos = new ByteArrayOutputStream();
393         {
394             SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
395             callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
396             callbackHandler.setIssuer("www.example.com");
397 
398             ConditionsBean conditions = new ConditionsBean();
399             conditions.setTokenPeriodMinutes(5);
400             conditions.setOneTimeUse(true);
401 
402             callbackHandler.setConditions(conditions);
403 
404             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
405             String action = WSHandlerConstants.SAML_TOKEN_SIGNED;
406             Properties properties = new Properties();
407             properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
408             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
409 
410             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
411             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
412         }
413 
414         //done signature; now test sig-verification:
415         {
416             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
417             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
418             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
419             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
420 
421             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
422             assertNotNull(document);
423         }
424     }
425 
426     /**
427      * Test that creates, sends and processes an unsigned SAML 2 authentication assertion
428      * with a ProxyRestriction Element
429      */
430     @Test
431     public void testSAML2ProxyRestriction() throws Exception {
432         ByteArrayOutputStream baos = new ByteArrayOutputStream();
433         {
434             SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
435             callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
436             callbackHandler.setIssuer("www.example.com");
437 
438             ConditionsBean conditions = new ConditionsBean();
439             conditions.setTokenPeriodMinutes(5);
440             ProxyRestrictionBean proxyRestriction = new ProxyRestrictionBean();
441             List<String> audiences = new ArrayList<>();
442             audiences.add("http://apache.org/one");
443             audiences.add("http://apache.org/two");
444             proxyRestriction.getAudienceURIs().addAll(audiences);
445             proxyRestriction.setCount(5);
446             conditions.setProxyRestriction(proxyRestriction);
447 
448             callbackHandler.setConditions(conditions);
449 
450             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
451             String action = WSHandlerConstants.SAML_TOKEN_SIGNED;
452             Properties properties = new Properties();
453             properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
454             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
455 
456             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
457             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
458         }
459 
460         //done signature; now test sig-verification:
461         {
462             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
463             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
464             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
465             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
466 
467             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
468             assertNotNull(document);
469         }
470     }
471 
472     /**
473      * Test that creates, sends and processes an unsigned SAML 2 authentication assertion
474      * with an AudienceRestriction Element
475      */
476     @Test
477     public void testSAML2AudienceRestriction() throws Exception {
478         ByteArrayOutputStream baos = new ByteArrayOutputStream();
479         {
480             SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
481             callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
482             callbackHandler.setIssuer("www.example.com");
483 
484             ConditionsBean conditions = new ConditionsBean();
485             conditions.setTokenPeriodMinutes(5);
486             List<String> audiences = new ArrayList<>();
487             audiences.add("http://apache.org/one");
488             audiences.add("http://apache.org/two");
489             AudienceRestrictionBean audienceRestrictionBean = new AudienceRestrictionBean();
490             audienceRestrictionBean.setAudienceURIs(audiences);
491             conditions.setAudienceRestrictions(Collections.singletonList(audienceRestrictionBean));
492 
493             callbackHandler.setConditions(conditions);
494 
495             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
496             String action = WSHandlerConstants.SAML_TOKEN_SIGNED;
497             Properties properties = new Properties();
498             properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
499             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
500 
501             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
502             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
503         }
504 
505         //done signature; now test sig-verification:
506         {
507             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
508             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
509             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
510             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
511 
512             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
513             assertNotNull(document);
514         }
515     }
516 
517     // Now test AudienceRestrictions with supplied restrictions
518     @Test
519     public void testSAML2AudienceRestrictionValidation() throws Exception {
520         ByteArrayOutputStream baos = new ByteArrayOutputStream();
521         List<String> audiences = new ArrayList<>();
522         {
523             SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
524             callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
525             callbackHandler.setIssuer("www.example.com");
526 
527             ConditionsBean conditions = new ConditionsBean();
528             conditions.setTokenPeriodMinutes(5);
529             audiences.add("http://apache.org/one");
530             audiences.add("http://apache.org/two");
531             AudienceRestrictionBean audienceRestrictionBean = new AudienceRestrictionBean();
532             audienceRestrictionBean.setAudienceURIs(audiences);
533             conditions.setAudienceRestrictions(Collections.singletonList(audienceRestrictionBean));
534 
535             callbackHandler.setConditions(conditions);
536 
537             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
538             String action = WSHandlerConstants.SAML_TOKEN_SIGNED;
539             Properties properties = new Properties();
540             properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
541             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
542 
543             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
544             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
545         }
546 
547         // This should fail as the expected audience isn't in the assertion
548         audiences.clear();
549         audiences.add("http://apache.org/three");
550         {
551             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
552             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
553             securityProperties.setAudienceRestrictions(audiences);
554             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
555             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
556 
557             try {
558                 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
559                 fail("XMLStreamException expected");
560             } catch (XMLStreamException e) {
561                 assertNotNull(e.getCause());
562             }
563         }
564 
565         // Now add the correct audience back in...
566         audiences.add("http://apache.org/one");
567         {
568             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
569             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
570             securityProperties.setAudienceRestrictions(audiences);
571             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
572             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
573 
574             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
575             assertNotNull(document);
576         }
577     }
578 
579     // Now test AudienceRestrictions with supplied restrictions
580     @Test
581     public void testSAML1AudienceRestrictionValidation() throws Exception {
582         ByteArrayOutputStream baos = new ByteArrayOutputStream();
583         List<String> audiences = new ArrayList<>();
584         {
585             SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
586             callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
587             callbackHandler.setIssuer("www.example.com");
588 
589             ConditionsBean conditions = new ConditionsBean();
590             conditions.setTokenPeriodMinutes(5);
591             audiences.add("http://apache.org/one");
592             audiences.add("http://apache.org/two");
593             AudienceRestrictionBean audienceRestrictionBean = new AudienceRestrictionBean();
594             audienceRestrictionBean.setAudienceURIs(audiences);
595             conditions.setAudienceRestrictions(Collections.singletonList(audienceRestrictionBean));
596 
597             callbackHandler.setConditions(conditions);
598 
599             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
600             String action = WSHandlerConstants.SAML_TOKEN_SIGNED;
601             Properties properties = new Properties();
602             properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
603             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
604 
605             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
606             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
607         }
608 
609         // This should fail as the expected audience isn't in the assertion
610         audiences.clear();
611         audiences.add("http://apache.org/three");
612         {
613             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
614             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
615             securityProperties.setAudienceRestrictions(audiences);
616             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
617             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
618 
619             try {
620                 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
621                 fail("XMLStreamException expected");
622             } catch (XMLStreamException e) {
623                 assertNotNull(e.getCause());
624             }
625         }
626 
627         // Now add the correct audience back in...
628         audiences.add("http://apache.org/one");
629         {
630             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
631             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
632             securityProperties.setAudienceRestrictions(audiences);
633             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
634             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
635 
636             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
637             assertNotNull(document);
638         }
639     }
640 
641     /**
642      * Test that creates, sends and processes an unsigned SAML 2 authentication assertion
643      * with two AudienceRestriction Elements
644      */
645     @Test
646     public void testSAML2AudienceRestrictionSeparateRestrictions() throws Exception {
647         ByteArrayOutputStream baos = new ByteArrayOutputStream();
648         {
649             SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
650             callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
651             callbackHandler.setIssuer("www.example.com");
652 
653             ConditionsBean conditions = new ConditionsBean();
654             conditions.setTokenPeriodMinutes(5);
655 
656             List<AudienceRestrictionBean> audiencesRestrictions =
657                 new ArrayList<>();
658             AudienceRestrictionBean audienceRestrictionBean = new AudienceRestrictionBean();
659             audienceRestrictionBean.setAudienceURIs(Collections.singletonList("http://apache.org/one"));
660             audiencesRestrictions.add(audienceRestrictionBean);
661 
662             audienceRestrictionBean = new AudienceRestrictionBean();
663             audienceRestrictionBean.setAudienceURIs(Collections.singletonList("http://apache.org/two"));
664             audiencesRestrictions.add(audienceRestrictionBean);
665 
666             conditions.setAudienceRestrictions(audiencesRestrictions);
667 
668             callbackHandler.setConditions(conditions);
669 
670             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
671             String action = WSHandlerConstants.SAML_TOKEN_SIGNED;
672             Properties properties = new Properties();
673             properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
674             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
675 
676             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
677             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
678         }
679 
680         //done signature; now test sig-verification:
681         {
682             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
683             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
684             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
685             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
686 
687             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
688             assertNotNull(document);
689         }
690     }
691 
692     // Now test AudienceRestrictions with supplied restrictions
693     @Test
694     public void testSAML1AudienceRestrictionSeparateRestrictionsValidation() throws Exception {
695         ByteArrayOutputStream baos = new ByteArrayOutputStream();
696         {
697             SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
698             callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
699             callbackHandler.setIssuer("www.example.com");
700 
701             ConditionsBean conditions = new ConditionsBean();
702             conditions.setTokenPeriodMinutes(5);
703 
704             List<AudienceRestrictionBean> audiencesRestrictions =
705                 new ArrayList<>();
706             AudienceRestrictionBean audienceRestrictionBean = new AudienceRestrictionBean();
707             audienceRestrictionBean.setAudienceURIs(Collections.singletonList("http://apache.org/one"));
708             audiencesRestrictions.add(audienceRestrictionBean);
709 
710             audienceRestrictionBean = new AudienceRestrictionBean();
711             audienceRestrictionBean.setAudienceURIs(Collections.singletonList("http://apache.org/two"));
712             audiencesRestrictions.add(audienceRestrictionBean);
713 
714             conditions.setAudienceRestrictions(audiencesRestrictions);
715 
716             callbackHandler.setConditions(conditions);
717 
718             InputStream sourceDocument = this.getClass().getClassLoader().getResourceAsStream("testdata/plain-soap-1.1.xml");
719             String action = WSHandlerConstants.SAML_TOKEN_SIGNED;
720             Properties properties = new Properties();
721             properties.put(WSHandlerConstants.SAML_CALLBACK_REF, callbackHandler);
722             Document securedDocument = doOutboundSecurityWithWSS4J(sourceDocument, action, properties);
723 
724             javax.xml.transform.Transformer transformer = TRANSFORMER_FACTORY.newTransformer();
725             transformer.transform(new DOMSource(securedDocument), new StreamResult(baos));
726         }
727 
728         // This should fail as the expected audience isn't in the assertion
729         List<String> audiences = new ArrayList<>();
730         audiences.add("http://apache.org/three");
731         {
732             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
733             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
734             securityProperties.setAudienceRestrictions(audiences);
735             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
736             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
737 
738             try {
739                 StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
740                 fail("XMLStreamException expected");
741             } catch (XMLStreamException e) {
742                 assertNotNull(e.getCause());
743             }
744         }
745 
746         // Now add the correct audience back in...
747         audiences.add("http://apache.org/one");
748         {
749             WSSSecurityProperties securityProperties = new WSSSecurityProperties();
750             securityProperties.loadSignatureVerificationKeystore(this.getClass().getClassLoader().getResource("receiver.jks"), "default".toCharArray());
751             securityProperties.setAudienceRestrictions(audiences);
752             InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties);
753             XMLStreamReader xmlStreamReader = wsSecIn.processInMessage(xmlInputFactory.createXMLStreamReader(new ByteArrayInputStream(baos.toByteArray())));
754 
755             Document document = StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), xmlStreamReader);
756             assertNotNull(document);
757         }
758     }
759 }