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 java.security.cert.X509Certificate;
23 import java.util.List;
24
25 import javax.security.auth.callback.CallbackHandler;
26
27 import org.apache.wss4j.common.WSEncryptionPart;
28 import org.apache.wss4j.common.crypto.Crypto;
29 import org.apache.wss4j.common.crypto.CryptoFactory;
30 import org.apache.wss4j.common.crypto.CryptoType;
31 import org.apache.wss4j.common.ext.WSSecurityException;
32 import org.apache.wss4j.common.saml.SAMLCallback;
33 import org.apache.wss4j.common.saml.SAMLUtil;
34 import org.apache.wss4j.common.saml.SamlAssertionWrapper;
35 import org.apache.wss4j.common.saml.builder.SAML1Constants;
36 import org.apache.wss4j.common.token.SecurityTokenReference;
37 import org.apache.wss4j.common.util.SOAPUtil;
38 import org.apache.wss4j.common.util.XMLUtils;
39 import org.apache.wss4j.dom.WSConstants;
40 import org.apache.wss4j.dom.WSDataRef;
41 import org.apache.wss4j.dom.common.KeystoreCallbackHandler;
42 import org.apache.wss4j.dom.common.SAML1CallbackHandler;
43
44 import org.apache.wss4j.dom.engine.WSSConfig;
45 import org.apache.wss4j.dom.engine.WSSecurityEngine;
46 import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
47 import org.apache.wss4j.dom.handler.RequestData;
48 import org.apache.wss4j.dom.handler.WSHandlerResult;
49 import org.apache.wss4j.dom.message.WSSecDKSign;
50 import org.apache.wss4j.dom.message.WSSecHeader;
51 import org.apache.wss4j.dom.util.WSSecurityUtil;
52
53 import org.junit.jupiter.api.Test;
54 import org.w3c.dom.Document;
55
56 import static org.junit.jupiter.api.Assertions.assertEquals;
57 import static org.junit.jupiter.api.Assertions.assertFalse;
58 import static org.junit.jupiter.api.Assertions.assertNotNull;
59 import static org.junit.jupiter.api.Assertions.assertTrue;
60
61
62
63
64
65 public class SamlTokenDerivedTest {
66 private static final org.slf4j.Logger LOG =
67 org.slf4j.LoggerFactory.getLogger(SamlTokenDerivedTest.class);
68 private WSSecurityEngine secEngine = new WSSecurityEngine();
69 private CallbackHandler callbackHandler = new KeystoreCallbackHandler();
70 private Crypto crypto;
71
72 public SamlTokenDerivedTest() throws Exception {
73 WSSConfig config = WSSConfig.getNewInstance();
74 secEngine.setWssConfig(config);
75 crypto = CryptoFactory.getInstance("crypto.properties");
76 }
77
78
79
80
81
82 @Test
83 @SuppressWarnings("unchecked")
84 public void testSAML1AuthnAssertionDerived() throws Exception {
85
86
87
88 SAML1CallbackHandler callbackHandler = new SAML1CallbackHandler();
89 callbackHandler.setStatement(SAML1CallbackHandler.Statement.AUTHN);
90 callbackHandler.setConfirmationMethod(SAML1Constants.CONF_SENDER_VOUCHES);
91 callbackHandler.setIssuer("www.example.com");
92
93 SAMLCallback samlCallback = new SAMLCallback();
94 SAMLUtil.doSAMLCallback(callbackHandler, samlCallback);
95 SamlAssertionWrapper samlAssertion = new SamlAssertionWrapper(samlCallback);
96
97 Document doc = SOAPUtil.toSOAPPart(SOAPUtil.SAMPLE_SOAP_MSG);
98 WSSecHeader secHeader = new WSSecHeader(doc);
99 secHeader.insertSecurityHeader();
100
101 SecurityTokenReference secRefSaml =
102 createSamlSTR(doc, samlAssertion, WSSConfig.getNewInstance());
103 secHeader.getSecurityHeaderElement().appendChild(samlAssertion.toDOM(doc));
104 secHeader.getSecurityHeaderElement().appendChild(secRefSaml.getElement());
105
106
107
108
109 WSSecDKSign sigBuilder = createDKSign(doc, secRefSaml, secHeader);
110 java.security.Key key =
111 crypto.getPrivateKey("16c73ab6-b892-458f-abf5-2f875f74882e", "security");
112 Document signedDoc = sigBuilder.build(key.getEncoded());
113
114 if (LOG.isDebugEnabled()) {
115 LOG.debug("SAML 1.1 Authn Assertion Derived (sender vouches):");
116 String outputString =
117 XMLUtils.prettyDocumentToString(signedDoc);
118 LOG.debug(outputString);
119 }
120
121
122 WSHandlerResult results = verify(signedDoc);
123 WSSecurityEngineResult actionResult =
124 results.getActionResults().get(WSConstants.ST_UNSIGNED).get(0);
125 SamlAssertionWrapper receivedSamlAssertion =
126 (SamlAssertionWrapper) actionResult.get(WSSecurityEngineResult.TAG_SAML_ASSERTION);
127 assertNotNull(receivedSamlAssertion);
128
129
130 actionResult = results.getActionResults().get(WSConstants.SIGN).get(0);
131 assertNotNull(actionResult);
132 assertFalse(actionResult.isEmpty());
133 final List<WSDataRef> refs =
134 (List<WSDataRef>) actionResult.get(WSSecurityEngineResult.TAG_DATA_REF_URIS);
135 assertTrue(refs.size() == 2);
136
137 WSDataRef wsDataRef = refs.get(0);
138 String xpath = wsDataRef.getXpath();
139 assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Body", xpath);
140
141 wsDataRef = refs.get(1);
142 xpath = wsDataRef.getXpath();
143 assertEquals("/SOAP-ENV:Envelope/SOAP-ENV:Header/wsse:Security/saml1:Assertion", xpath);
144 }
145
146
147
148
149 private SecurityTokenReference createSamlSTR(
150 Document doc,
151 SamlAssertionWrapper samlAssertion,
152 WSSConfig wssConfig
153 ) {
154 SecurityTokenReference secRefSaml = new SecurityTokenReference(doc);
155 String secRefID = wssConfig.getIdAllocator().createSecureId("STRSAMLId-", secRefSaml);
156 secRefSaml.setID(secRefID);
157
158 org.apache.wss4j.common.token.Reference ref =
159 new org.apache.wss4j.common.token.Reference(doc);
160 ref.setURI("#" + samlAssertion.getId());
161 ref.setValueType(WSConstants.WSS_SAML_KI_VALUE_TYPE);
162 secRefSaml.addTokenType(WSConstants.WSS_SAML_TOKEN_TYPE);
163 secRefSaml.setReference(ref);
164
165 return secRefSaml;
166 }
167
168
169
170
171
172 private WSSecDKSign createDKSign(
173 Document doc,
174 SecurityTokenReference secRefSaml,
175 WSSecHeader secHeader
176 ) throws WSSecurityException {
177 SecurityTokenReference secToken = new SecurityTokenReference(doc);
178 CryptoType cryptoType = new CryptoType(CryptoType.TYPE.ALIAS);
179 cryptoType.setAlias("16c73ab6-b892-458f-abf5-2f875f74882e");
180 X509Certificate[] certs = crypto.getX509Certificates(cryptoType);
181 secToken.setKeyIdentifierThumb(certs[0]);
182
183 WSSecDKSign sigBuilder = new WSSecDKSign(secHeader);
184 sigBuilder.setStrElem(secToken.getElement());
185 sigBuilder.setSignatureAlgorithm(WSConstants.HMAC_SHA1);
186 String soapNamespace = WSSecurityUtil.getSOAPNamespace(doc.getDocumentElement());
187 WSEncryptionPart encP =
188 new WSEncryptionPart(
189 WSConstants.ELEM_BODY,
190 soapNamespace,
191 "Content"
192 );
193 sigBuilder.getParts().add(encP);
194 encP = new WSEncryptionPart("STRTransform", "", "Element");
195 encP.setId(secRefSaml.getID());
196 encP.setElement(secRefSaml.getElement());
197 sigBuilder.getParts().add(encP);
198
199 return sigBuilder;
200 }
201
202
203
204
205
206
207
208
209 private WSHandlerResult verify(Document doc) throws Exception {
210 RequestData requestData = new RequestData();
211 requestData.setCallbackHandler(callbackHandler);
212 requestData.setDecCrypto(crypto);
213 requestData.setSigVerCrypto(crypto);
214 requestData.setValidateSamlSubjectConfirmation(false);
215
216 WSHandlerResult results = secEngine.processSecurityHeader(doc, requestData);
217
218 String outputString =
219 XMLUtils.prettyDocumentToString(doc);
220 assertTrue(outputString.indexOf("counter_port_type") > 0 ? true : false);
221 return results;
222 }
223
224 }