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  
20  package org.apache.ws.security.saml;
21  
22  import org.apache.ws.security.WSConstants;
23  import org.apache.ws.security.WSDataRef;
24  import org.apache.ws.security.WSSConfig;
25  import org.apache.ws.security.WSSecurityEngine;
26  import org.apache.ws.security.WSSecurityEngineResult;
27  import org.apache.ws.security.common.KeystoreCallbackHandler;
28  import org.apache.ws.security.common.SAML1CallbackHandler;
29  import org.apache.ws.security.common.SAML2CallbackHandler;
30  import org.apache.ws.security.common.SOAPUtil;
31  import org.apache.ws.security.components.crypto.Crypto;
32  import org.apache.ws.security.components.crypto.CryptoFactory;
33  import org.apache.ws.security.components.crypto.CryptoType;
34  import org.apache.ws.security.components.crypto.Merlin;
35  import org.apache.ws.security.message.WSSecHeader;
36  import org.apache.ws.security.saml.ext.AssertionWrapper;
37  import org.apache.ws.security.saml.ext.SAMLParms;
38  import org.apache.ws.security.saml.ext.bean.KeyInfoBean.CERT_IDENTIFIER;
39  import org.apache.ws.security.saml.ext.builder.SAML1Constants;
40  import org.apache.ws.security.saml.ext.builder.SAML2Constants;
41  import org.apache.ws.security.util.Loader;
42  import org.apache.ws.security.util.WSSecurityUtil;
43  import org.w3c.dom.Document;
44  
45  import javax.security.auth.callback.CallbackHandler;
46  
47  import java.io.InputStream;
48  import java.security.KeyStore;
49  import java.security.cert.X509Certificate;
50  import java.util.List;
51  
52  /**
53   * Test-case for sending and processing a signed (holder-of-key) SAML Assertion. These tests
54   * also cover the case of using the credential information in the SAML Subject to sign the
55   * SOAP body.
56   */
57  public class SignedSamlTokenHOKTest extends org.junit.Assert {
58      private static final org.apache.commons.logging.Log LOG = 
59          org.apache.commons.logging.LogFactory.getLog(SignedSamlTokenHOKTest.class);
60      private WSSecurityEngine secEngine = new WSSecurityEngine();
61      private CallbackHandler callbackHandler = new KeystoreCallbackHandler();
62      private Crypto trustCrypto = null;
63      private Crypto issuerCrypto = null;
64      private Crypto userCrypto = CryptoFactory.getInstance("wss40.properties");
65      
66      public SignedSamlTokenHOKTest() throws Exception {
67          WSSConfig.init();
68          // Load the issuer keystore
69          issuerCrypto = new Merlin();
70          KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
71          ClassLoader loader = Loader.getClassLoader(SignedSamlTokenHOKTest.class);
72          InputStream input = Merlin.loadInputStream(loader, "keys/wss40_server.jks");
73          keyStore.load(input, "security".toCharArray());
74          ((Merlin)issuerCrypto).setKeyStore(keyStore);
75          
76          // Load the server truststore
77          trustCrypto = new Merlin();
78          KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
79          input = Merlin.loadInputStream(loader, "keys/wss40CA.jks");
80          trustStore.load(input, "security".toCharArray());
81          ((Merlin)trustCrypto).setTrustStore(trustStore);
82      }
83      
84      /**
85       * Test that creates, sends and processes a signed SAML 1.1 authentication assertion.
86       */
87      @org.junit.Test
88      @SuppressWarnings("unchecked")
89      public void testSAML1AuthnAssertion() throws Exception {
90          SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
91          callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
92          callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
93          callbackHandler.setIssuer("www.example.com");
94          
95          SAMLParms samlParms = new SAMLParms();
96          samlParms.setCallbackHandler(callbackHandler);
97          AssertionWrapper assertion = new AssertionWrapper(samlParms);
98          assertion.signAssertion("wss40_server", "security", issuerCrypto, false);
99  
100         WSSecSignatureSAML wsSign = new WSSecSignatureSAML();
101         wsSign.setUserInfo("wss40", "security");
102         wsSign.setDigestAlgo("http://www.w3.org/2001/04/xmlenc#sha256");
103         wsSign.setSignatureAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
104         wsSign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
105 
106         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
107         WSSecHeader secHeader = new WSSecHeader();
108         secHeader.insertSecurityHeader(doc);
109 
110         Document signedDoc = 
111             wsSign.build(doc, userCrypto, assertion, null, null, null, secHeader);
112 
113         String outputString = 
114             org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
115         if (LOG.isDebugEnabled()) {
116             LOG.debug("Signed SAML 1.1 Authn Assertion (key holder):");
117             LOG.debug(outputString);
118         }
119         assertTrue(outputString.indexOf("http://www.w3.org/2001/04/xmlenc#sha256") != -1);
120         assertTrue(outputString.indexOf("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256") != -1);
121         
122         List<WSSecurityEngineResult> results = verify(signedDoc, trustCrypto);
123         
124         // Test we processed a SAML assertion
125         WSSecurityEngineResult actionResult =
126             WSSecurityUtil.fetchActionResult(results, WSConstants.ST_SIGNED);
127         AssertionWrapper receivedAssertion = 
128             (AssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
129         assertTrue(receivedAssertion != null);
130         assertTrue(receivedAssertion.isSigned());
131         assertTrue(receivedAssertion.getSignatureValue() != null);
132         
133         // Test we processed a signature (SOAP body)
134         actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
135         assertTrue(actionResult != null);
136         assertFalse(actionResult.isEmpty());
137         final List<WSDataRef> refs =
138             (List<WSDataRef>) actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
139         assertTrue(refs.size() == 1);
140         
141         WSDataRef wsDataRef = (WSDataRef)refs.get(0);
142         String xpath = wsDataRef.getXpath();
143         assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body", xpath);
144     }
145     
146     /**
147      * Test that creates, sends and processes a signed SAML 1.1 attribute assertion.
148      */
149     @org.junit.Test
150     public void testSAML1AttrAssertion() throws Exception {
151         SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
152         callbackHandler.setStatement(SAML1CallbackHandler.Statement.ATTR);
153         callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
154         callbackHandler.setIssuer("www.example.com");
155         
156         SAMLParms samlParms = new SAMLParms();
157         samlParms.setCallbackHandler(callbackHandler);
158         AssertionWrapper assertion = new AssertionWrapper(samlParms);
159         assertion.signAssertion("wss40_server", "security", issuerCrypto, false);
160         byte[] ephemeralKey = callbackHandler.getEphemeralKey();
161 
162         WSSecSignatureSAML wsSign = new WSSecSignatureSAML();
163         wsSign.setUserInfo("wss40", "security");
164         wsSign.setDigestAlgo("http://www.w3.org/2001/04/xmlenc#sha256");
165         wsSign.setSignatureAlgorithm(WSConstants.HMAC_SHA256);
166         wsSign.setKeyIdentifierType(WSConstants.X509_KEY_IDENTIFIER);
167         wsSign.setSecretKey(ephemeralKey);
168 
169         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
170         WSSecHeader secHeader = new WSSecHeader();
171         secHeader.insertSecurityHeader(doc);
172         Document signedDoc = 
173             wsSign.build(doc, userCrypto, assertion, null, null, null, secHeader);
174 
175         String outputString = 
176             org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
177         if (LOG.isDebugEnabled()) {
178             LOG.debug("Signed SAML 1.1 Attr Assertion (key holder):");
179             LOG.debug(outputString);
180         }
181         
182         /*TODO - Re-enable this when WSS-265 is fixed:
183          * https://issues.apache.org/jira/browse/WSS-265
184         List<WSSecurityEngineResult> results = verify(signedDoc, trustCrypto);
185         
186         // Test we processed a SAML assertion
187         WSSecurityEngineResult actionResult =
188             WSSecurityUtil.fetchActionResult(results, WSConstants.ST_SIGNED);
189         AssertionWrapper receivedAssertion = 
190             (AssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
191         assertTrue(receivedAssertion != null);
192         assertTrue(receivedAssertion.isSigned());
193         
194         // Test we processed a signature (SOAP body)
195         actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
196         assertTrue(actionResult != null);
197         assertFalse(actionResult.isEmpty());
198         final List<WSDataRef> refs =
199             (List<WSDataRef>) actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
200         assertTrue(refs.size() == 1);
201         
202         WSDataRef wsDataRef = (WSDataRef)refs.get(0);
203         String xpath = wsDataRef.getXpath();
204         assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body", xpath);
205         */
206     }
207     
208     /**
209      * Test that creates, sends and processes a signed SAML 2 authentication assertion.
210      */
211     @org.junit.Test
212     @SuppressWarnings("unchecked")
213     public void testSAML2AuthnAssertion() throws Exception {
214         SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
215         callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
216         callbackHandler.setConfirmationMethod(SAML2Constants.CONF_HOLDER_KEY);
217         callbackHandler.setIssuer("www.example.com");
218         
219         SAMLParms samlParms = new SAMLParms();
220         samlParms.setCallbackHandler(callbackHandler);
221         AssertionWrapper assertion = new AssertionWrapper(samlParms);
222         assertion.signAssertion("wss40_server", "security", issuerCrypto, false);
223 
224         WSSecSignatureSAML wsSign = new WSSecSignatureSAML();
225         wsSign.setUserInfo("wss40", "security");
226         wsSign.setDigestAlgo("http://www.w3.org/2001/04/xmlenc#sha256");
227         wsSign.setSignatureAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
228         wsSign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
229 
230         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
231         WSSecHeader secHeader = new WSSecHeader();
232         secHeader.insertSecurityHeader(doc);
233 
234         Document signedDoc = 
235             wsSign.build(doc, userCrypto, assertion, null, null, null, secHeader);
236 
237         String outputString = 
238             org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
239         if (LOG.isDebugEnabled()) {
240             LOG.debug("Signed SAML 2 Authn Assertion (key holder):");
241             LOG.debug(outputString);
242         }
243         assertTrue(outputString.indexOf("http://www.w3.org/2001/04/xmlenc#sha256") != -1);
244         assertTrue(outputString.indexOf("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256") != -1);
245         
246         List<WSSecurityEngineResult> results = verify(signedDoc, trustCrypto);
247         
248         // Test we processed a SAML assertion
249         WSSecurityEngineResult actionResult =
250             WSSecurityUtil.fetchActionResult(results, WSConstants.ST_SIGNED);
251         AssertionWrapper receivedAssertion = 
252             (AssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
253         assertTrue(receivedAssertion != null);
254         assertTrue(receivedAssertion.isSigned());
255         
256         // Test we processed a signature (SOAP body)
257         actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
258         assertTrue(actionResult != null);
259         assertFalse(actionResult.isEmpty());
260         final List<WSDataRef> refs =
261             (List<WSDataRef>) actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
262         assertTrue(refs.size() == 1);
263         
264         WSDataRef wsDataRef = (WSDataRef)refs.get(0);
265         String xpath = wsDataRef.getXpath();
266         assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body", xpath);
267     }
268     
269     /**
270      * Test that creates, sends and processes a signed SAML 2 attribute assertion.
271      */
272     @org.junit.Test
273     public void testSAML2AttrAssertion() throws Exception {
274         SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
275         callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
276         callbackHandler.setConfirmationMethod(SAML2Constants.CONF_HOLDER_KEY);
277         callbackHandler.setIssuer("www.example.com");
278         
279         SAMLParms samlParms = new SAMLParms();
280         samlParms.setCallbackHandler(callbackHandler);
281         AssertionWrapper assertion = new AssertionWrapper(samlParms);
282         assertion.signAssertion("wss40_server", "security", issuerCrypto, false);
283         byte[] ephemeralKey = callbackHandler.getEphemeralKey();
284 
285         WSSecSignatureSAML wsSign = new WSSecSignatureSAML();
286         wsSign.setUserInfo("wss40", "security");
287         wsSign.setDigestAlgo("http://www.w3.org/2001/04/xmlenc#sha256");
288         wsSign.setSignatureAlgorithm(WSConstants.HMAC_SHA256);
289         wsSign.setKeyIdentifierType(WSConstants.X509_KEY_IDENTIFIER);
290         wsSign.setSecretKey(ephemeralKey);
291 
292         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
293         WSSecHeader secHeader = new WSSecHeader();
294         secHeader.insertSecurityHeader(doc);
295 
296         Document signedDoc = 
297             wsSign.build(doc, userCrypto, assertion, null, null, null, secHeader);
298 
299         String outputString = 
300             org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
301         if (LOG.isDebugEnabled()) {
302             LOG.debug("Signed SAML 2 Attr Assertion (key holder):");
303             LOG.debug(outputString);
304         }
305         
306         /*
307          * TODO - Re-enable this when WSS-265 is fixed:
308          * https://issues.apache.org/jira/browse/WSS-265
309         List<WSSecurityEngineResult> results = verify(signedDoc, trustCrypto);
310         
311         // Test we processed a SAML assertion
312         WSSecurityEngineResult actionResult =
313             WSSecurityUtil.fetchActionResult(results, WSConstants.ST_SIGNED);
314         AssertionWrapper receivedAssertion = 
315             (AssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
316         assertTrue(receivedAssertion != null);
317         assertTrue(receivedAssertion.isSigned());
318         
319         // Test we processed a signature (SOAP body)
320         actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
321         assertTrue(actionResult != null);
322         assertFalse(actionResult.isEmpty());
323         final List<WSDataRef> refs =
324             (List<WSDataRef>) actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
325         assertTrue(refs.size() == 1);
326         
327         WSDataRef wsDataRef = (WSDataRef)refs.get(0);
328         String xpath = wsDataRef.getXpath();
329         assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body", xpath);
330         */
331     }
332     
333     /**
334      * Test that creates, sends and processes a signed SAML 1.1 authentication assertion,
335      * where the subject cert is referenced using IssuerSerial
336      */
337     @org.junit.Test
338     @SuppressWarnings("unchecked")
339     public void testSAML1AuthnAssertionIssuerSerial() throws Exception {
340         SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
341         callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
342         callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
343         callbackHandler.setCertIdentifier(CERT_IDENTIFIER.X509_ISSUER_SERIAL);
344         callbackHandler.setIssuer("www.example.com");
345         
346         SAMLParms samlParms = new SAMLParms();
347         samlParms.setCallbackHandler(callbackHandler);
348         AssertionWrapper assertion = new AssertionWrapper(samlParms);
349         assertion.signAssertion("wss40_server", "security", issuerCrypto, false);
350 
351         WSSecSignatureSAML wsSign = new WSSecSignatureSAML();
352         wsSign.setUserInfo("wss40", "security");
353         wsSign.setDigestAlgo("http://www.w3.org/2001/04/xmlenc#sha256");
354         wsSign.setSignatureAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
355         wsSign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
356 
357         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
358         WSSecHeader secHeader = new WSSecHeader();
359         secHeader.insertSecurityHeader(doc);
360 
361         Document signedDoc = 
362             wsSign.build(doc, userCrypto, assertion, null, null, null, secHeader);
363 
364         String outputString = 
365             org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
366         if (LOG.isDebugEnabled()) {
367             LOG.debug("SAML 1.1 Authn Assertion Issuer Serial (holder-of-key):");
368             LOG.debug(outputString);
369         }
370         assertTrue(outputString.contains("X509IssuerSerial"));
371         
372         List<WSSecurityEngineResult> results = verify(signedDoc, userCrypto);
373         WSSecurityEngineResult actionResult =
374             WSSecurityUtil.fetchActionResult(results, WSConstants.ST_SIGNED);
375         AssertionWrapper receivedAssertion = 
376             (AssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
377         assertTrue(receivedAssertion != null);
378         assertTrue(receivedAssertion.isSigned());
379         
380         // Test we processed a signature (SOAP body)
381         actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
382         assertTrue(actionResult != null);
383         assertFalse(actionResult.isEmpty());
384         final List<WSDataRef> refs =
385             (List<WSDataRef>) actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
386         assertTrue(refs.size() == 1);
387         
388         WSDataRef wsDataRef = (WSDataRef)refs.get(0);
389         String xpath = wsDataRef.getXpath();
390         assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body", xpath);
391     }
392     
393     /**
394      * Test that creates, sends and processes a signed SAML 1.1 authentication assertion,
395      * where the subject cert is referenced using a Key Value
396      */
397     @org.junit.Test
398     @SuppressWarnings("unchecked")
399     public void testSAML1AuthnAssertionKeyValue() throws Exception {
400         SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
401         callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
402         callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
403         callbackHandler.setCertIdentifier(CERT_IDENTIFIER.KEY_VALUE);
404         callbackHandler.setIssuer("www.example.com");
405         
406         SAMLParms samlParms = new SAMLParms();
407         samlParms.setCallbackHandler(callbackHandler);
408         AssertionWrapper assertion = new AssertionWrapper(samlParms);
409         assertion.signAssertion("wss40_server", "security", issuerCrypto, false);
410 
411         WSSecSignatureSAML wsSign = new WSSecSignatureSAML();
412         wsSign.setUserInfo("wss40", "security");
413         wsSign.setDigestAlgo("http://www.w3.org/2001/04/xmlenc#sha256");
414         wsSign.setSignatureAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
415         wsSign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
416 
417         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
418         WSSecHeader secHeader = new WSSecHeader();
419         secHeader.insertSecurityHeader(doc);
420 
421         Document signedDoc = 
422             wsSign.build(doc, userCrypto, assertion, null, null, null, secHeader);
423 
424         String outputString = 
425             org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
426         if (LOG.isDebugEnabled()) {
427             LOG.debug("SAML 1.1 Authn Assertion Key Value (holder-of-key):");
428             LOG.debug(outputString);
429         }
430         assertTrue(outputString.contains("KeyValue"));
431         
432         List<WSSecurityEngineResult> results = verify(signedDoc, userCrypto);
433         WSSecurityEngineResult actionResult =
434             WSSecurityUtil.fetchActionResult(results, WSConstants.ST_SIGNED);
435         AssertionWrapper receivedAssertion = 
436             (AssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
437         assertTrue(receivedAssertion != null);
438         assert receivedAssertion.isSigned();
439         
440         // Test we processed a signature (SOAP body)
441         actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
442         assertTrue(actionResult != null);
443         assertFalse(actionResult.isEmpty());
444         final List<WSDataRef> refs =
445             (List<WSDataRef>) actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
446         assertTrue(refs.size() == 1);
447         
448         WSDataRef wsDataRef = (WSDataRef)refs.get(0);
449         String xpath = wsDataRef.getXpath();
450         assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body", xpath);
451     }
452     
453     /**
454      * Test that creates, sends and processes a signed SAML 2 authentication assertion,
455      * where the subject cert is referenced using a Key Value
456      */
457     @org.junit.Test
458     @SuppressWarnings("unchecked")
459     public void testSAML2AuthnAssertionKeyValue() throws Exception {
460         SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
461         callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
462         callbackHandler.setConfirmationMethod(SAML2Constants.CONF_HOLDER_KEY);
463         callbackHandler.setCertIdentifier(CERT_IDENTIFIER.KEY_VALUE);
464         callbackHandler.setIssuer("www.example.com");
465         
466         SAMLParms samlParms = new SAMLParms();
467         samlParms.setCallbackHandler(callbackHandler);
468         AssertionWrapper assertion = new AssertionWrapper(samlParms);
469         assertion.signAssertion("wss40_server", "security", issuerCrypto, false);
470 
471         WSSecSignatureSAML wsSign = new WSSecSignatureSAML();
472         wsSign.setUserInfo("wss40", "security");
473         wsSign.setDigestAlgo("http://www.w3.org/2001/04/xmlenc#sha256");
474         wsSign.setSignatureAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
475         wsSign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
476 
477         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
478         WSSecHeader secHeader = new WSSecHeader();
479         secHeader.insertSecurityHeader(doc);
480 
481         Document signedDoc = 
482             wsSign.build(doc, userCrypto, assertion, null, null, null, secHeader);
483 
484         String outputString = 
485             org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
486         if (LOG.isDebugEnabled()) {
487             LOG.debug("SAML 2 Authn Assertion Key Value (holder-of-key):");
488             LOG.debug(outputString);
489         }
490         assertTrue(outputString.contains("KeyValue"));
491         
492         List<WSSecurityEngineResult> results = verify(signedDoc, userCrypto);
493         WSSecurityEngineResult actionResult =
494             WSSecurityUtil.fetchActionResult(results, WSConstants.ST_SIGNED);
495         AssertionWrapper receivedAssertion = 
496             (AssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
497         assertTrue(receivedAssertion != null);
498         assertTrue(receivedAssertion.isSigned());
499         
500         // Test we processed a signature (SOAP body)
501         actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
502         assertTrue(actionResult != null);
503         assertFalse(actionResult.isEmpty());
504         final List<WSDataRef> refs =
505             (List<WSDataRef>) actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
506         assertTrue(refs.size() == 1);
507         
508         WSDataRef wsDataRef = (WSDataRef)refs.get(0);
509         String xpath = wsDataRef.getXpath();
510         assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body", xpath);
511     }
512     
513     /**
514      * Test that creates, sends and processes a signed SAML 1.1 authentication assertion.
515      * The difference is that we don't trust the user signature, but as we trust the
516      * signature of the issuer, we have (indirect) trust.
517      */
518     @org.junit.Test
519     @SuppressWarnings("unchecked")
520     public void testSAML1AuthnAssertionTrust() throws Exception {
521         SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
522         callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
523         callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
524         callbackHandler.setIssuer("www.example.com");
525         Crypto crypto = CryptoFactory.getInstance("crypto.properties");
526         CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
527         cryptoType.setAlias("16c73ab6-b892-458f-abf5-2f875f74882e");
528         X509Certificate[] certs = crypto.getX509Certificates(cryptoType);
529         callbackHandler.setCerts(certs);
530         
531         SAMLParms samlParms = new SAMLParms();
532         samlParms.setCallbackHandler(callbackHandler);
533         AssertionWrapper assertion = new AssertionWrapper(samlParms);
534         assertion.signAssertion("wss40_server", "security", issuerCrypto, false);
535 
536         WSSecSignatureSAML wsSign = new WSSecSignatureSAML();
537         wsSign.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
538         wsSign.setDigestAlgo("http://www.w3.org/2001/04/xmlenc#sha256");
539         wsSign.setSignatureAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
540         wsSign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
541 
542         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
543         WSSecHeader secHeader = new WSSecHeader();
544         secHeader.insertSecurityHeader(doc);
545 
546         Document signedDoc = 
547             wsSign.build(doc, crypto, assertion, null, null, null, secHeader);
548 
549         String outputString = 
550             org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
551         if (LOG.isDebugEnabled()) {
552             LOG.debug("Signed SAML 1.1 Authn Assertion (key holder):");
553             LOG.debug(outputString);
554         }
555         
556         List<WSSecurityEngineResult> results = verify(signedDoc, trustCrypto);
557         
558         // Test we processed a SAML assertion
559         WSSecurityEngineResult actionResult =
560             WSSecurityUtil.fetchActionResult(results, WSConstants.ST_SIGNED);
561         AssertionWrapper receivedAssertion = 
562             (AssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
563         assertTrue(receivedAssertion != null);
564         assertTrue(receivedAssertion.isSigned());
565         
566         // Test we processed a signature (SOAP body)
567         actionResult = WSSecurityUtil.fetchActionResult(results, WSConstants.SIGN);
568         assertTrue(actionResult != null);
569         assertFalse(actionResult.isEmpty());
570         final List<WSDataRef> refs =
571             (List<WSDataRef>) actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
572         assertTrue(refs.size() == 1);
573         
574         WSDataRef wsDataRef = (WSDataRef)refs.get(0);
575         String xpath = wsDataRef.getXpath();
576         assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body", xpath);
577     }
578     
579     /**
580      * Verifies the soap envelope
581      * 
582      * @param doc
583      * @throws Exception Thrown when there is a problem in verification
584      */
585     private List<WSSecurityEngineResult> verify(Document doc, Crypto sigCrypto) throws Exception {
586         List<WSSecurityEngineResult> results = 
587             secEngine.processSecurityHeader(
588                 doc, null, callbackHandler, sigCrypto, userCrypto
589             );
590         String outputString = 
591             org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(doc);
592         assertTrue(outputString.indexOf("counter_port_type") > 0 ? true : false);
593         return results;
594     }
595 
596 }