1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20 package org.apache.wss4j.dom.saml;
21
22 import org.apache.wss4j.common.WSEncryptionPart;
23 import org.apache.wss4j.common.saml.SamlAssertionWrapper;
24 import org.apache.wss4j.common.util.SOAPUtil;
25 import org.apache.wss4j.dom.WSConstants;
26 import org.apache.wss4j.dom.WSDataRef;
27 import org.apache.wss4j.dom.common.KeystoreCallbackHandler;
28 import org.apache.wss4j.dom.common.SAML1CallbackHandler;
29 import org.apache.wss4j.dom.common.SAML2CallbackHandler;
30
31 import org.apache.wss4j.dom.engine.WSSConfig;
32 import org.apache.wss4j.dom.engine.WSSecurityEngine;
33 import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
34 import org.apache.wss4j.dom.handler.RequestData;
35 import org.apache.wss4j.dom.handler.WSHandlerResult;
36 import org.apache.wss4j.common.crypto.Crypto;
37 import org.apache.wss4j.common.crypto.CryptoFactory;
38 import org.apache.wss4j.common.crypto.Merlin;
39 import org.apache.wss4j.common.saml.SAMLCallback;
40 import org.apache.wss4j.common.saml.SAMLUtil;
41 import org.apache.wss4j.common.saml.builder.SAML1Constants;
42 import org.apache.wss4j.common.saml.builder.SAML2Constants;
43 import org.apache.wss4j.common.util.KeyUtils;
44 import org.apache.wss4j.common.util.Loader;
45 import org.apache.wss4j.common.util.XMLUtils;
46 import org.apache.wss4j.dom.message.WSSecEncrypt;
47 import org.apache.wss4j.dom.message.WSSecHeader;
48
49 import org.junit.jupiter.api.Test;
50 import org.w3c.dom.Document;
51 import org.w3c.dom.Element;
52 import org.w3c.dom.Node;
53
54 import java.io.InputStream;
55 import java.security.KeyStore;
56 import java.util.List;
57
58 import javax.crypto.KeyGenerator;
59 import javax.crypto.SecretKey;
60 import javax.security.auth.callback.CallbackHandler;
61
62 import static org.junit.jupiter.api.Assertions.assertEquals;
63 import static org.junit.jupiter.api.Assertions.assertFalse;
64 import static org.junit.jupiter.api.Assertions.assertNotNull;
65 import static org.junit.jupiter.api.Assertions.assertTrue;
66
67
68
69
70 public class SamlReferenceTest {
71 private static final org.slf4j.Logger LOG =
72 org.slf4j.LoggerFactory.getLogger(SamlReferenceTest.class);
73 private WSSecurityEngine secEngine = new WSSecurityEngine();
74 private CallbackHandler callbackHandler = new KeystoreCallbackHandler();
75 private Crypto crypto = CryptoFactory.getInstance("crypto.properties");
76 private Crypto trustCrypto;
77 private Crypto issuerCrypto;
78 private Crypto userCrypto = CryptoFactory.getInstance("wss40.properties");
79
80 public SamlReferenceTest() throws Exception {
81 WSSConfig config = WSSConfig.getNewInstance();
82 secEngine.setWssConfig(config);
83
84
85 issuerCrypto = new Merlin();
86 KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
87 ClassLoader loader = Loader.getClassLoader(SignedSamlTokenHOKTest.class);
88 InputStream input = Merlin.loadInputStream(loader, "keys/wss40_server.jks");
89 keyStore.load(input, "security".toCharArray());
90 input.close();
91 ((Merlin)issuerCrypto).setKeyStore(keyStore);
92
93
94 trustCrypto = new Merlin();
95 KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
96 input = Merlin.loadInputStream(loader, "keys/wss40CA.jks");
97 trustStore.load(input, "security".toCharArray());
98 input.close();
99 ((Merlin)trustCrypto).setTrustStore(trustStore);
100 }
101
102
103
104
105
106
107 @Test
108 @SuppressWarnings("unchecked")
109 public void testSAML1SVKeyIdentifier() throws Exception {
110 SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
111 callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
112 callbackHandler.setConfirmationMethod(SAML1Constants.CONF_SENDER_VOUCHES);
113 callbackHandler.setIssuer("www.example.com");
114
115 SAMLCallback samlCallback = new SAMLCallback();
116 SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
117 SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback);
118
119 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
120 WSSecHeader secHeader = new WSSecHeader(doc);
121 secHeader.insertSecurityHeader();
122
123 WSSecSignatureSAML wsSign = new WSSecSignatureSAML(secHeader);
124 wsSign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
125 Document signedDoc =
126 wsSign.build(
127 null, samlAssertion, crypto, "16c73ab6-b892-458f-abf5-2f875f74882e",
128 "security"
129 );
130
131 String outputString =
132 XMLUtils.prettyDocumentToString(signedDoc);
133 if (LOG.isDebugEnabled()) {
134 LOG.debug("Signed SAML message Key Identifier (sender vouches):");
135 LOG.debug(outputString);
136 }
137 assertTrue(outputString.contains(WSConstants.WSS_SAML_KI_VALUE_TYPE));
138 assertTrue(outputString.contains(WSConstants.WSS_SAML_TOKEN_TYPE));
139
140 WSHandlerResult results = verify(signedDoc, crypto, null);
141 WSSecurityEngineResult actionResult =
142 results.getActionResults().get(WSConstants.ST_UNSIGNED).get(0);
143 SamlAssertionWrapper receivedSamlAssertion =
144 (SamlAssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
145 assertNotNull(receivedSamlAssertion);
146
147
148 actionResult = results.getActionResults().get(WSConstants.SIGN).get(0);
149 assertNotNull(actionResult);
150 assertFalse(actionResult.isEmpty());
151 final List<WSDataRef> refs =
152 (List<WSDataRef>) actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
153 assertTrue(refs.size() == 2);
154
155 WSDataRef wsDataRef = refs.get(0);
156 String xpath = wsDataRef.getXpath();
157 assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body", xpath);
158
159 wsDataRef = refs.get(1);
160 xpath = wsDataRef.getXpath();
161 assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/saml1:Assertion", xpath);
162 }
163
164
165
166
167
168
169
170 @Test
171 @SuppressWarnings("unchecked")
172 public void testSAML1SVDirectReference() throws Exception {
173 SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
174 callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
175 callbackHandler.setConfirmationMethod(SAML1Constants.CONF_SENDER_VOUCHES);
176 callbackHandler.setIssuer("www.example.com");
177
178 SAMLCallback samlCallback = new SAMLCallback();
179 SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
180 SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback);
181
182 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
183 WSSecHeader secHeader = new WSSecHeader(doc);
184 secHeader.insertSecurityHeader();
185
186 WSSecSignatureSAML wsSign = new WSSecSignatureSAML(secHeader);
187 wsSign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
188 wsSign.setUseDirectReferenceToAssertion(true);
189 Document signedDoc =
190 wsSign.build(
191 null, samlAssertion, crypto, "16c73ab6-b892-458f-abf5-2f875f74882e",
192 "security"
193 );
194
195 String outputString =
196 XMLUtils.prettyDocumentToString(doc);
197 if (LOG.isDebugEnabled()) {
198 LOG.debug("Signed SAML message Direct Reference (sender vouches):");
199 LOG.debug(outputString);
200 }
201 assertTrue(outputString.contains(WSConstants.WSS_SAML_KI_VALUE_TYPE));
202 assertTrue(outputString.contains(WSConstants.WSS_SAML_TOKEN_TYPE));
203
204 WSHandlerResult results = verify(signedDoc, crypto, null);
205 WSSecurityEngineResult actionResult =
206 results.getActionResults().get(WSConstants.ST_UNSIGNED).get(0);
207 SamlAssertionWrapper receivedSamlAssertion =
208 (SamlAssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
209 assertNotNull(receivedSamlAssertion);
210
211
212 actionResult = results.getActionResults().get(WSConstants.SIGN).get(0);
213 assertNotNull(actionResult);
214 assertFalse(actionResult.isEmpty());
215 final List<WSDataRef> refs =
216 (List<WSDataRef>) actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
217 assertTrue(refs.size() == 2);
218
219 WSDataRef wsDataRef = refs.get(0);
220 String xpath = wsDataRef.getXpath();
221 assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body", xpath);
222
223 wsDataRef = refs.get(1);
224 xpath = wsDataRef.getXpath();
225 assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/saml1:Assertion", xpath);
226 }
227
228
229
230
231
232
233
234 @Test
235 @SuppressWarnings("unchecked")
236 public void testSAML1HOKKeyIdentifier() throws Exception {
237 SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
238 callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
239 callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
240 callbackHandler.setIssuer("www.example.com");
241
242 SAMLCallback samlCallback = new SAMLCallback();
243 SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
244 SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback);
245
246 samlAssertion.signAssertion("wss40_server", "security", issuerCrypto, false);
247
248 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
249 WSSecHeader secHeader = new WSSecHeader(doc);
250 secHeader.insertSecurityHeader();
251
252 WSSecSignatureSAML wsSign = new WSSecSignatureSAML(secHeader);
253 wsSign.setUserInfo("wss40", "security");
254 wsSign.setDigestAlgo("http://www.w3.org/2001/04/xmlenc#sha256");
255 wsSign.setSignatureAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
256
257 Document signedDoc =
258 wsSign.build(userCrypto, samlAssertion, null, null, null);
259
260 String outputString =
261 XMLUtils.prettyDocumentToString(doc);
262 if (LOG.isDebugEnabled()) {
263 LOG.debug("Signed SAML message Key Identifier (holder-of-key):");
264 LOG.debug(outputString);
265 }
266 assertTrue(outputString.contains(WSConstants.WSS_SAML_KI_VALUE_TYPE));
267 assertTrue(outputString.contains(WSConstants.WSS_SAML_TOKEN_TYPE));
268
269 WSHandlerResult results = verify(signedDoc, trustCrypto, null);
270 WSSecurityEngineResult actionResult =
271 results.getActionResults().get(WSConstants.ST_SIGNED).get(0);
272 SamlAssertionWrapper receivedSamlAssertion =
273 (SamlAssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
274 assertNotNull(receivedSamlAssertion);
275 assertTrue(receivedSamlAssertion.isSigned());
276
277
278 actionResult = results.getActionResults().get(WSConstants.SIGN).get(0);
279 assertNotNull(actionResult);
280 assertFalse(actionResult.isEmpty());
281 final List<WSDataRef> refs =
282 (List<WSDataRef>) actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
283 assertTrue(refs.size() == 1);
284
285 WSDataRef wsDataRef = refs.get(0);
286 String xpath = wsDataRef.getXpath();
287 assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body", xpath);
288 }
289
290
291
292
293
294
295
296
297 @Test
298 @SuppressWarnings("unchecked")
299 public void testSAML1HOKDirectReference() throws Exception {
300 SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
301 callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
302 callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
303 callbackHandler.setIssuer("www.example.com");
304
305 SAMLCallback samlCallback = new SAMLCallback();
306 SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
307 SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback);
308
309 samlAssertion.signAssertion("wss40_server", "security", issuerCrypto, false);
310
311 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
312 WSSecHeader secHeader = new WSSecHeader(doc);
313 secHeader.insertSecurityHeader();
314
315 WSSecSignatureSAML wsSign = new WSSecSignatureSAML(secHeader);
316 wsSign.setUserInfo("wss40", "security");
317 wsSign.setDigestAlgo("http://www.w3.org/2001/04/xmlenc#sha256");
318 wsSign.setSignatureAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
319 wsSign.setUseDirectReferenceToAssertion(true);
320 wsSign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
321
322 Document signedDoc =
323 wsSign.build(userCrypto, samlAssertion, null, null, null);
324
325 String outputString =
326 XMLUtils.prettyDocumentToString(doc);
327 if (LOG.isDebugEnabled()) {
328 LOG.debug("Signed SAML message Direct Reference (holder-of-key):");
329 LOG.debug(outputString);
330 }
331 assertTrue(outputString.contains(WSConstants.WSS_SAML_KI_VALUE_TYPE));
332 assertTrue(outputString.contains(WSConstants.WSS_SAML_TOKEN_TYPE));
333
334 WSHandlerResult results = verify(signedDoc, trustCrypto, null);
335 WSSecurityEngineResult actionResult =
336 results.getActionResults().get(WSConstants.ST_SIGNED).get(0);
337 SamlAssertionWrapper receivedSamlAssertion =
338 (SamlAssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
339 assertNotNull(receivedSamlAssertion);
340 assertTrue(receivedSamlAssertion.isSigned());
341
342
343 actionResult = results.getActionResults().get(WSConstants.SIGN).get(0);
344 assertNotNull(actionResult);
345 assertFalse(actionResult.isEmpty());
346 final List<WSDataRef> refs =
347 (List<WSDataRef>) actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
348 assertTrue(refs.size() == 1);
349
350 WSDataRef wsDataRef = refs.get(0);
351 String xpath = wsDataRef.getXpath();
352 assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body", xpath);
353 }
354
355
356
357
358
359
360
361
362
363
364 @Test
365 public void testAssertionBelowSTR() throws Exception {
366 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
367 WSSecHeader secHeader = new WSSecHeader(doc);
368 secHeader.insertSecurityHeader();
369
370 SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
371 callbackHandler.setStatement(SAML1CallbackHandler.Statement.ATTR);
372 callbackHandler.setConfirmationMethod(SAML1Constants.CONF_SENDER_VOUCHES);
373 callbackHandler.setIssuer("www.example.com");
374
375 SAMLCallback samlCallback = new SAMLCallback();
376 SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
377
378 SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback);
379 Crypto crypto = CryptoFactory.getInstance("crypto.properties");
380 WSSecSignatureSAML wsSign = new WSSecSignatureSAML(secHeader);
381 wsSign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
382 wsSign.build(null, samlAssertion, crypto,
383 "16c73ab6-b892-458f-abf5-2f875f74882e", "security"
384 );
385
386 WSSecEncrypt builder = new WSSecEncrypt(secHeader);
387 builder.setUserInfo("16c73ab6-b892-458f-abf5-2f875f74882e");
388 builder.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
389
390 KeyGenerator keyGen = KeyUtils.getKeyGenerator(WSConstants.AES_128);
391 SecretKey symmetricKey = keyGen.generateKey();
392 Document encryptedDoc = builder.build(crypto, symmetricKey);
393
394
395
396
397 Element secHeaderElement = secHeader.getSecurityHeaderElement();
398 Node assertionNode =
399 secHeaderElement.getElementsByTagNameNS(WSConstants.SAML_NS, "Assertion").item(0);
400 secHeaderElement.removeChild(assertionNode);
401 secHeaderElement.appendChild(assertionNode);
402
403 String outputString =
404 XMLUtils.prettyDocumentToString(encryptedDoc);
405 if (LOG.isDebugEnabled()) {
406 LOG.debug("Encrypted message:");
407 LOG.debug(outputString);
408 }
409 assertTrue(outputString.contains(WSConstants.WSS_SAML_KI_VALUE_TYPE));
410 assertTrue(outputString.contains(WSConstants.WSS_SAML_TOKEN_TYPE));
411
412 verify(encryptedDoc, crypto, crypto);
413 }
414
415
416
417
418
419
420
421
422 @Test
423 @SuppressWarnings("unchecked")
424 public void testSAML1HOKEKKeyIdentifier() throws Exception {
425
426 SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
427 callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
428 callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
429 callbackHandler.setIssuer("www.example.com");
430
431 SAMLCallback samlCallback = new SAMLCallback();
432 SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
433 SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback);
434
435 samlAssertion.signAssertion("wss40_server", "security", issuerCrypto, false);
436
437 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
438 WSSecHeader secHeader = new WSSecHeader(doc);
439 Node assertionNode = samlAssertion.toDOM(doc);
440 secHeader.insertSecurityHeader();
441 secHeader.getSecurityHeaderElement().appendChild(assertionNode);
442
443
444 WSSecEncrypt builder = new WSSecEncrypt(secHeader);
445 builder.setUserInfo("wss40");
446 builder.setSymmetricEncAlgorithm(WSConstants.TRIPLE_DES);
447 builder.setKeyIdentifierType(WSConstants.CUSTOM_KEY_IDENTIFIER);
448 builder.setCustomEKTokenValueType(WSConstants.WSS_SAML_KI_VALUE_TYPE);
449 builder.setCustomEKTokenId(samlAssertion.getId());
450
451 KeyGenerator keyGen = KeyUtils.getKeyGenerator(WSConstants.TRIPLE_DES);
452 SecretKey symmetricKey = keyGen.generateKey();
453 builder.prepare(userCrypto, symmetricKey);
454
455 WSEncryptionPart encP =
456 new WSEncryptionPart(
457 "add", "http://ws.apache.org/counter/counter_port_type", "Element"
458 );
459 builder.getParts().add(encP);
460 Element refElement = builder.encrypt(symmetricKey);
461 builder.addInternalRefElement(refElement);
462 builder.appendToHeader();
463
464 String outputString =
465 XMLUtils.prettyDocumentToString(doc);
466 if (LOG.isDebugEnabled()) {
467 LOG.debug("Encrypted SAML 1.1 message Key Identifier (holder-of-key):");
468 LOG.debug(outputString);
469 }
470 assertTrue(outputString.contains(WSConstants.WSS_SAML_KI_VALUE_TYPE));
471 assertTrue(outputString.contains(WSConstants.WSS_SAML_TOKEN_TYPE));
472
473 WSHandlerResult results = verify(doc, trustCrypto, userCrypto);
474 WSSecurityEngineResult actionResult =
475 results.getActionResults().get(WSConstants.ST_SIGNED).get(0);
476 SamlAssertionWrapper receivedSamlAssertion =
477 (SamlAssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
478 assertNotNull(receivedSamlAssertion);
479 assertTrue(receivedSamlAssertion.isSigned());
480
481
482 actionResult = results.getActionResults().get(WSConstants.ENCR).get(0);
483 assertNotNull(actionResult);
484 assertFalse(actionResult.isEmpty());
485 final List<WSDataRef> refs =
486 (List<WSDataRef>) actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
487 assertTrue(refs.size() == 1);
488
489 WSDataRef wsDataRef = refs.get(0);
490 String xpath = wsDataRef.getXpath();
491 assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body/add", xpath);
492
493 }
494
495
496
497
498
499
500
501
502 @Test
503 @SuppressWarnings("unchecked")
504 public void testSAML1HOKEKDirectReference() throws Exception {
505
506 SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
507 callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
508 callbackHandler.setConfirmationMethod(SAML1Constants.CONF_HOLDER_KEY);
509 callbackHandler.setIssuer("www.example.com");
510
511 SAMLCallback samlCallback = new SAMLCallback();
512 SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
513 SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback);
514
515 samlAssertion.signAssertion("wss40_server", "security", issuerCrypto, false);
516 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
517 WSSecHeader secHeader = new WSSecHeader(doc);
518 Node assertionNode = samlAssertion.toDOM(doc);
519 secHeader.insertSecurityHeader();
520 secHeader.getSecurityHeaderElement().appendChild(assertionNode);
521
522
523 WSSecEncrypt builder = new WSSecEncrypt(secHeader);
524 builder.setUserInfo("wss40");
525 builder.setSymmetricEncAlgorithm(WSConstants.TRIPLE_DES);
526 builder.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
527 builder.setCustomEKTokenValueType(WSConstants.WSS_SAML_KI_VALUE_TYPE);
528 builder.setCustomEKTokenId(samlAssertion.getId());
529
530 KeyGenerator keyGen = KeyUtils.getKeyGenerator(WSConstants.TRIPLE_DES);
531 SecretKey symmetricKey = keyGen.generateKey();
532 builder.prepare(userCrypto, symmetricKey);
533
534 WSEncryptionPart encP =
535 new WSEncryptionPart(
536 "add", "http://ws.apache.org/counter/counter_port_type", "Element"
537 );
538 builder.getParts().add(encP);
539 Element refElement = builder.encrypt(symmetricKey);
540 builder.addInternalRefElement(refElement);
541 builder.appendToHeader();
542
543 String outputString =
544 XMLUtils.prettyDocumentToString(doc);
545 if (LOG.isDebugEnabled()) {
546 LOG.debug("Encrypted SAML 1.1 message Direct Reference (holder-of-key):");
547 LOG.debug(outputString);
548 }
549 assertTrue(outputString.contains(WSConstants.WSS_SAML_KI_VALUE_TYPE));
550 assertTrue(outputString.contains(WSConstants.WSS_SAML_TOKEN_TYPE));
551
552 WSHandlerResult results = verify(doc, trustCrypto, userCrypto);
553 WSSecurityEngineResult actionResult =
554 results.getActionResults().get(WSConstants.ST_SIGNED).get(0);
555 SamlAssertionWrapper receivedSamlAssertion =
556 (SamlAssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
557 assertNotNull(receivedSamlAssertion);
558 assertTrue(receivedSamlAssertion.isSigned());
559
560
561 actionResult = results.getActionResults().get(WSConstants.ENCR).get(0);
562 assertNotNull(actionResult);
563 assertFalse(actionResult.isEmpty());
564 final List<WSDataRef> refs =
565 (List<WSDataRef>) actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
566 assertTrue(refs.size() == 1);
567
568 WSDataRef wsDataRef = refs.get(0);
569 String xpath = wsDataRef.getXpath();
570 assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body/add", xpath);
571 }
572
573
574
575
576
577
578 @Test
579 @SuppressWarnings("unchecked")
580 public void testSAML2SVKeyIdentifier() throws Exception {
581 SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
582 callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
583 callbackHandler.setConfirmationMethod(SAML2Constants.CONF_SENDER_VOUCHES);
584 callbackHandler.setIssuer("www.example.com");
585
586 SAMLCallback samlCallback = new SAMLCallback();
587 SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
588 SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback);
589
590 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
591 WSSecHeader secHeader = new WSSecHeader(doc);
592 secHeader.insertSecurityHeader();
593
594 WSSecSignatureSAML wsSign = new WSSecSignatureSAML(secHeader);
595 wsSign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
596 Document signedDoc =
597 wsSign.build(
598 null, samlAssertion, crypto, "16c73ab6-b892-458f-abf5-2f875f74882e",
599 "security"
600 );
601
602 String outputString =
603 XMLUtils.prettyDocumentToString(signedDoc);
604 if (LOG.isDebugEnabled()) {
605 LOG.debug("Signed SAML2 message Key Identifier (sender vouches):");
606 LOG.debug(outputString);
607 }
608 assertTrue(outputString.contains(WSConstants.WSS_SAML2_KI_VALUE_TYPE));
609 assertTrue(outputString.contains(WSConstants.WSS_SAML2_TOKEN_TYPE));
610
611 WSHandlerResult results = verify(signedDoc, crypto, null);
612 WSSecurityEngineResult actionResult =
613 results.getActionResults().get(WSConstants.ST_UNSIGNED).get(0);
614 SamlAssertionWrapper receivedSamlAssertion =
615 (SamlAssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
616 assertNotNull(receivedSamlAssertion);
617
618
619 actionResult = results.getActionResults().get(WSConstants.SIGN).get(0);
620 assertNotNull(actionResult);
621 assertFalse(actionResult.isEmpty());
622 final List<WSDataRef> refs =
623 (List<WSDataRef>) actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
624 assertTrue(refs.size() == 2);
625
626 WSDataRef wsDataRef = refs.get(0);
627 String xpath = wsDataRef.getXpath();
628 assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body", xpath);
629
630 wsDataRef = refs.get(1);
631 xpath = wsDataRef.getXpath();
632 assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/saml2:Assertion", xpath);
633 }
634
635
636
637
638
639
640 @Test
641 @SuppressWarnings("unchecked")
642 public void testSAML2SVDirectReference() throws Exception {
643 SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
644 callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
645 callbackHandler.setConfirmationMethod(SAML2Constants.CONF_SENDER_VOUCHES);
646 callbackHandler.setIssuer("www.example.com");
647
648 SAMLCallback samlCallback = new SAMLCallback();
649 SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
650 SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback);
651
652 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
653 WSSecHeader secHeader = new WSSecHeader(doc);
654 secHeader.insertSecurityHeader();
655
656 WSSecSignatureSAML wsSign = new WSSecSignatureSAML(secHeader);
657 wsSign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
658 wsSign.setUseDirectReferenceToAssertion(true);
659 Document signedDoc =
660 wsSign.build(
661 null, samlAssertion, crypto, "16c73ab6-b892-458f-abf5-2f875f74882e",
662 "security"
663 );
664
665 String outputString =
666 XMLUtils.prettyDocumentToString(doc);
667 if (LOG.isDebugEnabled()) {
668 LOG.debug("Signed SAML2 message Direct Reference (sender vouches):");
669 LOG.debug(outputString);
670 }
671 assertFalse(outputString.contains(WSConstants.WSS_SAML2_KI_VALUE_TYPE));
672 assertTrue(outputString.contains(WSConstants.WSS_SAML2_TOKEN_TYPE));
673
674 WSHandlerResult results = verify(signedDoc, crypto, null);
675 WSSecurityEngineResult actionResult =
676 results.getActionResults().get(WSConstants.ST_UNSIGNED).get(0);
677 SamlAssertionWrapper receivedSamlAssertion =
678 (SamlAssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
679 assertNotNull(receivedSamlAssertion);
680
681
682 actionResult = results.getActionResults().get(WSConstants.SIGN).get(0);
683 assertNotNull(actionResult);
684 assertFalse(actionResult.isEmpty());
685 final List<WSDataRef> refs =
686 (List<WSDataRef>) actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
687 assertTrue(refs.size() == 2);
688
689 WSDataRef wsDataRef = refs.get(0);
690 String xpath = wsDataRef.getXpath();
691 assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body", xpath);
692
693 wsDataRef = refs.get(1);
694 xpath = wsDataRef.getXpath();
695 assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/saml2:Assertion", xpath);
696 }
697
698
699
700
701
702
703
704 @Test
705 @SuppressWarnings("unchecked")
706 public void testSAML2HOKKeyIdentifier() throws Exception {
707 SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
708 callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
709 callbackHandler.setConfirmationMethod(SAML2Constants.CONF_HOLDER_KEY);
710 callbackHandler.setIssuer("www.example.com");
711
712 SAMLCallback samlCallback = new SAMLCallback();
713 SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
714 SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback);
715
716 samlAssertion.signAssertion("wss40_server", "security", issuerCrypto, false);
717
718 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
719 WSSecHeader secHeader = new WSSecHeader(doc);
720 secHeader.insertSecurityHeader();
721
722 WSSecSignatureSAML wsSign = new WSSecSignatureSAML(secHeader);
723 wsSign.setUserInfo("wss40", "security");
724 wsSign.setDigestAlgo("http://www.w3.org/2001/04/xmlenc#sha256");
725 wsSign.setSignatureAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
726
727 Document signedDoc =
728 wsSign.build(userCrypto, samlAssertion, null, null, null);
729
730 String outputString =
731 XMLUtils.prettyDocumentToString(doc);
732 if (LOG.isDebugEnabled()) {
733 LOG.debug("Signed SAML2 message Key Identifier (holder-of-key):");
734 LOG.debug(outputString);
735 }
736 assertTrue(outputString.contains(WSConstants.WSS_SAML2_KI_VALUE_TYPE));
737 assertTrue(outputString.contains(WSConstants.WSS_SAML2_TOKEN_TYPE));
738
739 WSHandlerResult results = verify(signedDoc, trustCrypto, null);
740 WSSecurityEngineResult actionResult =
741 results.getActionResults().get(WSConstants.ST_SIGNED).get(0);
742 SamlAssertionWrapper receivedSamlAssertion =
743 (SamlAssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
744 assertNotNull(receivedSamlAssertion);
745 assertTrue(receivedSamlAssertion.isSigned());
746
747
748 actionResult = results.getActionResults().get(WSConstants.SIGN).get(0);
749 assertNotNull(actionResult);
750 assertFalse(actionResult.isEmpty());
751 final List<WSDataRef> refs =
752 (List<WSDataRef>) actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
753 assertTrue(refs.size() == 1);
754
755 WSDataRef wsDataRef = refs.get(0);
756 String xpath = wsDataRef.getXpath();
757 assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body", xpath);
758 }
759
760
761
762
763
764
765
766
767 @Test
768 @SuppressWarnings("unchecked")
769 public void testSAML2HOKDirectReference() throws Exception {
770 SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
771 callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
772 callbackHandler.setConfirmationMethod(SAML2Constants.CONF_HOLDER_KEY);
773 callbackHandler.setIssuer("www.example.com");
774
775 SAMLCallback samlCallback = new SAMLCallback();
776 SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
777 SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback);
778
779 samlAssertion.signAssertion("wss40_server", "security", issuerCrypto, false);
780
781 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
782 WSSecHeader secHeader = new WSSecHeader(doc);
783 secHeader.insertSecurityHeader();
784
785
786 WSSecSignatureSAML wsSign = new WSSecSignatureSAML(secHeader);
787 wsSign.setUserInfo("wss40", "security");
788 wsSign.setDigestAlgo("http://www.w3.org/2001/04/xmlenc#sha256");
789 wsSign.setSignatureAlgorithm("http://www.w3.org/2001/04/xmldsig-more#rsa-sha256");
790 wsSign.setUseDirectReferenceToAssertion(true);
791 wsSign.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
792
793 Document signedDoc =
794 wsSign.build(userCrypto, samlAssertion, null, null, null);
795
796 String outputString =
797 XMLUtils.prettyDocumentToString(doc);
798 if (LOG.isDebugEnabled()) {
799 LOG.debug("Signed SAML2 message Direct Reference (holder-of-key):");
800 LOG.debug(outputString);
801 }
802 assertFalse(outputString.contains(WSConstants.WSS_SAML2_KI_VALUE_TYPE));
803 assertTrue(outputString.contains(WSConstants.WSS_SAML2_TOKEN_TYPE));
804
805 WSHandlerResult results = verify(signedDoc, trustCrypto, null);
806 WSSecurityEngineResult actionResult =
807 results.getActionResults().get(WSConstants.ST_SIGNED).get(0);
808 SamlAssertionWrapper receivedSamlAssertion =
809 (SamlAssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
810 assertNotNull(receivedSamlAssertion);
811 assertTrue(receivedSamlAssertion.isSigned());
812
813
814 actionResult = results.getActionResults().get(WSConstants.SIGN).get(0);
815 assertNotNull(actionResult);
816 assertFalse(actionResult.isEmpty());
817 final List<WSDataRef> refs =
818 (List<WSDataRef>) actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
819 assertTrue(refs.size() == 1);
820
821 WSDataRef wsDataRef = refs.get(0);
822 String xpath = wsDataRef.getXpath();
823 assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body", xpath);
824 }
825
826
827
828
829
830
831
832 @Test
833 @SuppressWarnings("unchecked")
834 public void testSAML2HOKEKKeyIdentifier() throws Exception {
835
836 SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
837 callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
838 callbackHandler.setConfirmationMethod(SAML2Constants.CONF_HOLDER_KEY);
839 callbackHandler.setIssuer("www.example.com");
840
841 SAMLCallback samlCallback = new SAMLCallback();
842 SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
843 SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback);
844
845 samlAssertion.signAssertion("wss40_server", "security", issuerCrypto, false);
846
847 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
848 WSSecHeader secHeader = new WSSecHeader(doc);
849 Node assertionNode = samlAssertion.toDOM(doc);
850 secHeader.insertSecurityHeader();
851 secHeader.getSecurityHeaderElement().appendChild(assertionNode);
852
853
854 WSSecEncrypt builder = new WSSecEncrypt(secHeader);
855 builder.setUserInfo("wss40");
856 builder.setSymmetricEncAlgorithm(WSConstants.TRIPLE_DES);
857 builder.setKeyIdentifierType(WSConstants.CUSTOM_KEY_IDENTIFIER);
858 builder.setCustomEKTokenValueType(WSConstants.WSS_SAML2_KI_VALUE_TYPE);
859 builder.setCustomEKTokenId(samlAssertion.getId());
860
861 KeyGenerator keyGen = KeyUtils.getKeyGenerator(WSConstants.TRIPLE_DES);
862 SecretKey symmetricKey = keyGen.generateKey();
863 builder.prepare(userCrypto, symmetricKey);
864
865 WSEncryptionPart encP =
866 new WSEncryptionPart(
867 "add", "http://ws.apache.org/counter/counter_port_type", "Element"
868 );
869 builder.getParts().add(encP);
870 Element refElement = builder.encrypt(symmetricKey);
871 builder.addInternalRefElement(refElement);
872 builder.appendToHeader();
873
874 String outputString =
875 XMLUtils.prettyDocumentToString(doc);
876 if (LOG.isDebugEnabled()) {
877 LOG.debug("Encrypted SAML 2 message Key Identifier (holder-of-key):");
878 LOG.debug(outputString);
879 }
880 assertTrue(outputString.contains(WSConstants.WSS_SAML2_KI_VALUE_TYPE));
881 assertTrue(outputString.contains(WSConstants.WSS_SAML2_TOKEN_TYPE));
882
883 WSHandlerResult results = verify(doc, trustCrypto, userCrypto);
884 WSSecurityEngineResult actionResult =
885 results.getActionResults().get(WSConstants.ST_SIGNED).get(0);
886 SamlAssertionWrapper receivedSamlAssertion =
887 (SamlAssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
888 assertNotNull(receivedSamlAssertion);
889 assertTrue(receivedSamlAssertion.isSigned());
890
891
892 actionResult = results.getActionResults().get(WSConstants.ENCR).get(0);
893 assertNotNull(actionResult);
894 assertFalse(actionResult.isEmpty());
895 final List<WSDataRef> refs =
896 (List<WSDataRef>) actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
897 assertTrue(refs.size() == 1);
898
899 WSDataRef wsDataRef = refs.get(0);
900 String xpath = wsDataRef.getXpath();
901 assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body/add", xpath);
902
903 }
904
905
906
907
908
909
910
911 @Test
912 @SuppressWarnings("unchecked")
913 public void testSAML2HOKEKDirectReference() throws Exception {
914
915 SAML2CallbackHandler callbackHandler = new SAML2CallbackHandler();
916 callbackHandler.setStatement(SAML2CallbackHandler.Statement.AUTHN);
917 callbackHandler.setConfirmationMethod(SAML2Constants.CONF_HOLDER_KEY);
918 callbackHandler.setIssuer("www.example.com");
919
920 SAMLCallback samlCallback = new SAMLCallback();
921 SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
922 SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback);
923
924 samlAssertion.signAssertion("wss40_server", "security", issuerCrypto, false);
925
926 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
927 WSSecHeader secHeader = new WSSecHeader(doc);
928 Node assertionNode = samlAssertion.toDOM(doc);
929 secHeader.insertSecurityHeader();
930 secHeader.getSecurityHeaderElement().appendChild(assertionNode);
931
932
933 WSSecEncrypt builder = new WSSecEncrypt(secHeader);
934 builder.setUserInfo("wss40");
935 builder.setSymmetricEncAlgorithm(WSConstants.TRIPLE_DES);
936 builder.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
937 builder.setCustomEKTokenValueType(WSConstants.WSS_SAML2_KI_VALUE_TYPE);
938 builder.setCustomEKTokenId(samlAssertion.getId());
939
940 KeyGenerator keyGen = KeyUtils.getKeyGenerator(WSConstants.TRIPLE_DES);
941 SecretKey symmetricKey = keyGen.generateKey();
942 builder.prepare(userCrypto, symmetricKey);
943
944 WSEncryptionPart encP =
945 new WSEncryptionPart(
946 "add", "http://ws.apache.org/counter/counter_port_type", "Element"
947 );
948 builder.getParts().add(encP);
949 Element refElement = builder.encrypt(symmetricKey);
950 builder.addInternalRefElement(refElement);
951 builder.appendToHeader();
952
953 String outputString =
954 XMLUtils.prettyDocumentToString(doc);
955 if (LOG.isDebugEnabled()) {
956 LOG.debug("Encrypted SAML 2 message Direct Reference (holder-of-key):");
957 LOG.debug(outputString);
958 }
959 assertFalse(outputString.contains(WSConstants.WSS_SAML2_KI_VALUE_TYPE));
960 assertTrue(outputString.contains(WSConstants.WSS_SAML2_TOKEN_TYPE));
961
962 WSHandlerResult results = verify(doc, trustCrypto, userCrypto);
963 WSSecurityEngineResult actionResult =
964 results.getActionResults().get(WSConstants.ST_SIGNED).get(0);
965 SamlAssertionWrapper receivedSamlAssertion =
966 (SamlAssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
967 assertNotNull(receivedSamlAssertion);
968 assertTrue(receivedSamlAssertion.isSigned());
969
970
971 actionResult = results.getActionResults().get(WSConstants.ENCR).get(0);
972 assertNotNull(actionResult);
973 assertFalse(actionResult.isEmpty());
974 final List<WSDataRef> refs =
975 (List<WSDataRef>) actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
976 assertTrue(refs.size() == 1);
977
978 WSDataRef wsDataRef = refs.get(0);
979 String xpath = wsDataRef.getXpath();
980 assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body/add", xpath);
981
982 }
983
984
985
986
987
988
989
990
991 private WSHandlerResult verify(
992 Document doc, Crypto verifyCrypto, Crypto decCrypto
993 ) throws Exception {
994 RequestData requestData = new RequestData();
995 requestData.setCallbackHandler(callbackHandler);
996 requestData.setDecCrypto(decCrypto);
997 requestData.setSigVerCrypto(verifyCrypto);
998 requestData.setValidateSamlSubjectConfirmation(false);
999
1000 WSHandlerResult results = secEngine.processSecurityHeader(doc, requestData);
1001
1002 String outputString =
1003 XMLUtils.prettyDocumentToString(doc);
1004 assertTrue(outputString.indexOf("counter_port_type") > 0 ? true : false);
1005 return results;
1006 }
1007
1008 }