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.WSSConfig;
24  import org.apache.ws.security.WSSecurityEngine;
25  import org.apache.ws.security.WSSecurityEngineResult;
26  import org.apache.ws.security.common.KeystoreCallbackHandler;
27  import org.apache.ws.security.common.SAML1CallbackHandler;
28  import org.apache.ws.security.common.SAML2CallbackHandler;
29  import org.apache.ws.security.common.SOAPUtil;
30  import org.apache.ws.security.components.crypto.Crypto;
31  import org.apache.ws.security.components.crypto.CryptoFactory;
32  import org.apache.ws.security.message.WSSecHeader;
33  import org.apache.ws.security.message.WSSecSAMLToken;
34  import org.apache.ws.security.saml.ext.AssertionWrapper;
35  import org.apache.ws.security.saml.ext.SAMLParms;
36  import org.apache.ws.security.saml.ext.builder.SAML1Constants;
37  import org.apache.ws.security.saml.ext.builder.SAML2Constants;
38  import org.apache.ws.security.util.WSSecurityUtil;
39  
40  import org.w3c.dom.Document;
41  
42  import java.util.List;
43  
44  /**
45   * Test-case for sending and processing a signed (holder-of-key) SAML Assertion. These tests
46   * just cover the case of creating and signing the Assertion, and not using the credential 
47   * information in the SAML Subject to sign the SOAP body.
48   */
49  public class SamlTokenHOKTest extends org.junit.Assert {
50      private static final org.apache.commons.logging.Log LOG = 
51          org.apache.commons.logging.LogFactory.getLog(SamlTokenHOKTest.class);
52      private WSSecurityEngine secEngine = new WSSecurityEngine();
53      private Crypto crypto = null;
54      
55      public SamlTokenHOKTest() throws Exception {
56          WSSConfig.init();
57          crypto = CryptoFactory.getInstance("crypto.properties");
58      }
59  
60      /**
61       * Test that creates, sends and processes a signed SAML 1.1 authentication assertion.
62       */
63      @org.junit.Test
64      public void testSAML1AuthnAssertion() throws Exception {
65          SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
66          callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
67          callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
68          callbackHandler.setIssuer("www.example.com");
69          
70          SAMLParms samlParms = new SAMLParms();
71          samlParms.setCallbackHandler(callbackHandler);
72          AssertionWrapper assertion = new AssertionWrapper(samlParms);
73          assertion.signAssertion("16c73ab6-b892-458f-abf5-2f875f74882e", "security", crypto, false);
74  
75          WSSecSAMLToken wsSign = new WSSecSAMLToken();
76  
77          Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
78          WSSecHeader secHeader = new WSSecHeader();
79          secHeader.insertSecurityHeader(doc);
80          
81          Document signedDoc = wsSign.build(doc, assertion, secHeader);
82  
83          if (LOG.isDebugEnabled()) {
84              LOG.debug("SAML 1.1 Authn Assertion (holder-of-key):");
85              String outputString = 
86                  org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
87              LOG.debug(outputString);
88          }
89          
90          List<WSSecurityEngineResult> results = verify(signedDoc);
91          WSSecurityEngineResult actionResult =
92              WSSecurityUtil.fetchActionResult(results, WSConstants.ST_SIGNED);
93          AssertionWrapper receivedAssertion = 
94              (AssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
95          assertTrue(receivedAssertion != null);
96          assertTrue(receivedAssertion.isSigned());
97          assertNotNull(receivedAssertion.assertionToString());
98      }
99      
100     /**
101      * Test that creates, sends and processes a signed SAML 1 authentication assertion, where
102      * the configuration is loaded from a properties file
103      */
104     @org.junit.Test
105     public void testSAML1AuthnAssertionFromProperties() throws Exception {
106         SAMLIssuer saml = SAMLIssuerFactory.getInstance("saml_hok.properties");
107         AssertionWrapper assertion = saml.newAssertion();
108 
109         WSSecSAMLToken wsSign = new WSSecSAMLToken();
110 
111         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
112         WSSecHeader secHeader = new WSSecHeader();
113         secHeader.insertSecurityHeader(doc);
114         
115         Document signedDoc = wsSign.build(doc, assertion, secHeader);
116 
117         if (LOG.isDebugEnabled()) {
118             LOG.debug("SAML 1.1 Authn Assertion (holder-of-key):");
119             String outputString = 
120                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
121             LOG.debug(outputString);
122         }
123         
124         List<WSSecurityEngineResult> results = verify(signedDoc);
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     }
132     
133     /**
134      * Test that creates, sends and processes a signed SAML 1.1 attribute assertion.
135      */
136     @org.junit.Test
137     public void testSAML1AttrAssertion() throws Exception {
138         SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
139         callbackHandler.setStatement(SAML1CallbackHandler.Statement.ATTR);
140         callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
141         callbackHandler.setIssuer("www.example.com");
142         
143         SAMLParms samlParms = new SAMLParms();
144         samlParms.setCallbackHandler(callbackHandler);
145         AssertionWrapper assertion = new AssertionWrapper(samlParms);
146         assertion.signAssertion("16c73ab6-b892-458f-abf5-2f875f74882e", "security", crypto, false);
147 
148 
149         WSSecSAMLToken wsSign = new WSSecSAMLToken();
150 
151         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
152         WSSecHeader secHeader = new WSSecHeader();
153         secHeader.insertSecurityHeader(doc);
154         
155         Document signedDoc = wsSign.build(doc, assertion, secHeader);
156 
157         if (LOG.isDebugEnabled()) {
158             LOG.debug("SAML 1.1 Attr Assertion (holder-of-key):");
159             String outputString = 
160                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(signedDoc);
161             LOG.debug(outputString);
162         }
163         
164         Crypto decCrypto = CryptoFactory.getInstance("wss40.properties");
165         List<WSSecurityEngineResult> results = 
166             secEngine.processSecurityHeader(doc, null, new KeystoreCallbackHandler(), crypto, decCrypto);
167         String outputString = 
168             org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(doc);
169         assertTrue(outputString.indexOf("counter_port_type") > 0 ? true : false);
170         
171         WSSecurityEngineResult actionResult =
172             WSSecurityUtil.fetchActionResult(results, WSConstants.ST_SIGNED);
173         AssertionWrapper receivedAssertion = 
174             (AssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
175         assertTrue(receivedAssertion != null);
176         assertTrue(receivedAssertion.isSigned());
177     }
178     
179     /**
180      * Test that creates, sends and processes an unsigned SAML 2 authentication assertion.
181      */
182     @org.junit.Test
183     public void testSAML2AuthnAssertion() throws Exception {
184         SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
185         callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
186         callbackHandler.setConfirmationMethod(SAML2Constants.CONF_HOLDER_KEY);
187         callbackHandler.setIssuer("www.example.com");
188         
189         SAMLParms samlParms = new SAMLParms();
190         samlParms.setCallbackHandler(callbackHandler);
191         AssertionWrapper assertion = new AssertionWrapper(samlParms);
192         assertion.signAssertion("16c73ab6-b892-458f-abf5-2f875f74882e", "security", crypto, false);
193 
194         WSSecSAMLToken wsSign = new WSSecSAMLToken();
195 
196         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
197         WSSecHeader secHeader = new WSSecHeader();
198         secHeader.insertSecurityHeader(doc);
199         
200         Document unsignedDoc = wsSign.build(doc, assertion, secHeader);
201 
202         if (LOG.isDebugEnabled()) {
203             LOG.debug("SAML 2 Authn Assertion (holder-of-key):");
204             String outputString = 
205                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(unsignedDoc);
206             LOG.debug(outputString);
207         }
208         
209         List<WSSecurityEngineResult> results = verify(unsignedDoc);
210         WSSecurityEngineResult actionResult =
211             WSSecurityUtil.fetchActionResult(results, WSConstants.ST_SIGNED);
212         AssertionWrapper receivedAssertion = 
213             (AssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
214         assertTrue(receivedAssertion != null);
215         assertTrue(receivedAssertion.isSigned());
216     }
217     
218     /**
219      * Test that creates, sends and processes an unsigned SAML 2 attribute assertion.
220      */
221     @org.junit.Test
222     public void testSAML2AttrAssertion() throws Exception {
223         SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
224         callbackHandler.setStatement(SAML2CallbackHandler.Statement.ATTR);
225         callbackHandler.setConfirmationMethod(SAML2Constants.CONF_HOLDER_KEY);
226         callbackHandler.setIssuer("www.example.com");
227         
228         SAMLParms samlParms = new SAMLParms();
229         samlParms.setCallbackHandler(callbackHandler);
230         AssertionWrapper assertion = new AssertionWrapper(samlParms);
231         assertion.signAssertion("16c73ab6-b892-458f-abf5-2f875f74882e", "security", crypto, false);
232 
233 
234         WSSecSAMLToken wsSign = new WSSecSAMLToken();
235 
236         Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
237         WSSecHeader secHeader = new WSSecHeader();
238         secHeader.insertSecurityHeader(doc);
239         
240         Document unsignedDoc = wsSign.build(doc, assertion, secHeader);
241 
242         if (LOG.isDebugEnabled()) {
243             LOG.debug("SAML 2 Attr Assertion (holder-of-key):");
244             String outputString = 
245                 org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(unsignedDoc);
246             LOG.debug(outputString);
247         }
248         
249         Crypto decCrypto = CryptoFactory.getInstance("wss40.properties");
250         List<WSSecurityEngineResult> results = 
251             secEngine.processSecurityHeader(doc, null, new KeystoreCallbackHandler(), crypto, decCrypto);
252         String outputString = 
253             org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(doc);
254         assertTrue(outputString.indexOf("counter_port_type") > 0 ? true : false);
255         
256         WSSecurityEngineResult actionResult =
257             WSSecurityUtil.fetchActionResult(results, WSConstants.ST_SIGNED);
258         AssertionWrapper receivedAssertion = 
259             (AssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
260         assertTrue(receivedAssertion != null);
261     }
262 
263     /**
264      * Verifies the soap envelope
265      * <p/>
266      * 
267      * @param envelope 
268      * @throws Exception Thrown when there is a problem in verification
269      */
270     private List<WSSecurityEngineResult> verify(Document doc) throws Exception {
271         List<WSSecurityEngineResult> results = 
272             secEngine.processSecurityHeader(doc, null, null, crypto);
273         String outputString = 
274             org.apache.ws.security.util.XMLUtils.PrettyDocumentToString(doc);
275         assertTrue(outputString.indexOf("counter_port_type") > 0 ? true : false);
276         return results;
277     }
278 
279 }