|
7 | 7 | import java.util.List; |
8 | 8 | import java.util.Map; |
9 | 9 |
|
10 | | -import javax.servlet.http.HttpServletRequest; |
11 | 10 | import javax.xml.xpath.XPathExpressionException; |
12 | 11 |
|
13 | 12 | import com.onelogin.saml2.model.SubjectConfirmationIssue; |
@@ -80,17 +79,19 @@ public class SamlResponse { |
80 | 79 | * |
81 | 80 | * @param settings |
82 | 81 | * Saml2Settings object. Setting data |
83 | | - * @param request |
84 | | - * HttpServletRequest object to be processed (Contains GET and POST parameters, session, ...). |
| 82 | + * @param requestURL |
| 83 | + * the URL where the response was POST'ed (not including query parameters) |
| 84 | + * @param samlResponseParameter |
| 85 | + * the contents of the {@code SAMLResponse} query parameter |
85 | 86 | * |
86 | 87 | * @throws Exception |
87 | 88 | */ |
88 | | - public SamlResponse(Saml2Settings settings, HttpServletRequest request) throws Exception { |
| 89 | + public SamlResponse(Saml2Settings settings, String requestURL, String samlResponseParameter) throws Exception { |
89 | 90 | this.settings = settings; |
90 | 91 |
|
91 | | - if (request != null) { |
92 | | - currentUrl = request.getRequestURL().toString(); |
93 | | - loadXmlFromBase64(request.getParameter("SAMLResponse")); |
| 92 | + if (requestURL != null && samlResponseParameter != null) { |
| 93 | + currentUrl = requestURL; |
| 94 | + loadXmlFromBase64(samlResponseParameter); |
94 | 95 | } |
95 | 96 | } |
96 | 97 |
|
@@ -183,7 +184,7 @@ public boolean isValid(String requestId) { |
183 | 184 | if (requestId != null && !ObjectUtils.equals(responseInResponseTo, requestId)) { |
184 | 185 | throw new Exception("The InResponseTo of the Response: " + responseInResponseTo |
185 | 186 | + ", does not match the ID of the AuthNRequest sent by the SP: " + requestId); |
186 | | - } |
| 187 | + } |
187 | 188 |
|
188 | 189 | if (!this.encrypted && settings.getWantAssertionsEncrypted()) { |
189 | 190 | throw new Exception("The assertion of the Response is not encrypted and the SP requires it"); |
@@ -285,68 +286,68 @@ public boolean isValid(String requestId) { |
285 | 286 | } |
286 | 287 | } |
287 | 288 |
|
288 | | - // Check SubjectConfirmation, at least one SubjectConfirmation must be valid |
| 289 | + // Check SubjectConfirmation, at least one SubjectConfirmation must be valid |
289 | 290 | private void validateSubjectConfirmation(String responseInResponseTo) throws Exception { |
290 | 291 | final List<SubjectConfirmationIssue> validationIssues = new ArrayList<>(); |
291 | | - boolean validSubjectConfirmation = false; |
292 | | - NodeList subjectConfirmationNodes = this.queryAssertion("/saml:Subject/saml:SubjectConfirmation"); |
293 | | - for (int i = 0; i < subjectConfirmationNodes.getLength(); i++) { |
294 | | - Node scn = subjectConfirmationNodes.item(i); |
295 | | - |
296 | | - Node method = scn.getAttributes().getNamedItem("Method"); |
297 | | - if (method != null && !method.getNodeValue().equals(Constants.CM_BEARER)) { |
298 | | - continue; |
299 | | - } |
| 292 | + boolean validSubjectConfirmation = false; |
| 293 | + NodeList subjectConfirmationNodes = this.queryAssertion("/saml:Subject/saml:SubjectConfirmation"); |
| 294 | + for (int i = 0; i < subjectConfirmationNodes.getLength(); i++) { |
| 295 | + Node scn = subjectConfirmationNodes.item(i); |
| 296 | + |
| 297 | + Node method = scn.getAttributes().getNamedItem("Method"); |
| 298 | + if (method != null && !method.getNodeValue().equals(Constants.CM_BEARER)) { |
| 299 | + continue; |
| 300 | + } |
300 | 301 |
|
301 | | - NodeList subjectConfirmationDataNodes = scn.getChildNodes(); |
302 | | - for (int c = 0; c < subjectConfirmationDataNodes.getLength(); c++) { |
303 | | - if (subjectConfirmationDataNodes.item(c).getLocalName() != null && subjectConfirmationDataNodes.item(c).getLocalName().equals("SubjectConfirmationData")) { |
| 302 | + NodeList subjectConfirmationDataNodes = scn.getChildNodes(); |
| 303 | + for (int c = 0; c < subjectConfirmationDataNodes.getLength(); c++) { |
| 304 | + if (subjectConfirmationDataNodes.item(c).getLocalName() != null && subjectConfirmationDataNodes.item(c).getLocalName().equals("SubjectConfirmationData")) { |
304 | 305 |
|
305 | | - Node recipient = subjectConfirmationDataNodes.item(c).getAttributes().getNamedItem("Recipient"); |
| 306 | + Node recipient = subjectConfirmationDataNodes.item(c).getAttributes().getNamedItem("Recipient"); |
306 | 307 | if (recipient == null) { |
307 | 308 | validationIssues.add(new SubjectConfirmationIssue(i, "SubjectConfirmationData doesn't contain a Recipient")); |
308 | 309 | continue; |
309 | 310 | } |
310 | 311 |
|
311 | 312 | if (!recipient.getNodeValue().equals(currentUrl)) { |
312 | 313 | validationIssues.add(new SubjectConfirmationIssue(i, "SubjectConfirmationData doesn't match a valid Recipient")); |
313 | | - continue; |
314 | | - } |
| 314 | + continue; |
| 315 | + } |
315 | 316 |
|
316 | | - Node inResponseTo = subjectConfirmationDataNodes.item(c).getAttributes().getNamedItem("InResponseTo"); |
| 317 | + Node inResponseTo = subjectConfirmationDataNodes.item(c).getAttributes().getNamedItem("InResponseTo"); |
317 | 318 | if (inResponseTo == null && responseInResponseTo != null || |
318 | 319 | inResponseTo != null && !inResponseTo.getNodeValue().equals(responseInResponseTo)) { |
319 | 320 | validationIssues.add(new SubjectConfirmationIssue(i, "SubjectConfirmationData has an invalid InResponseTo value"));; |
320 | | - continue; |
321 | | - } |
| 321 | + continue; |
| 322 | + } |
322 | 323 |
|
323 | | - |
324 | | - Node notOnOrAfter = subjectConfirmationDataNodes.item(c).getAttributes().getNamedItem("NotOnOrAfter"); |
| 324 | + |
| 325 | + Node notOnOrAfter = subjectConfirmationDataNodes.item(c).getAttributes().getNamedItem("NotOnOrAfter"); |
325 | 326 | if (notOnOrAfter == null) { |
326 | 327 | validationIssues.add(new SubjectConfirmationIssue(i, "SubjectConfirmationData doesn't contain a NotOnOrAfter attribute")); |
327 | 328 | continue; |
328 | 329 | } |
329 | 330 |
|
330 | | - DateTime noa = Util.parseDateTime(notOnOrAfter.getNodeValue()); |
331 | | - if (noa.isEqualNow() || noa.isBeforeNow()) { |
| 331 | + DateTime noa = Util.parseDateTime(notOnOrAfter.getNodeValue()); |
| 332 | + if (noa.isEqualNow() || noa.isBeforeNow()) { |
332 | 333 | validationIssues.add(new SubjectConfirmationIssue(i, "SubjectConfirmationData is no longer valid")); |
333 | | - continue; |
334 | | - } |
| 334 | + continue; |
| 335 | + } |
335 | 336 |
|
336 | | - Node notBefore = subjectConfirmationDataNodes.item(c).getAttributes().getNamedItem("NotBefore"); |
337 | | - if (notBefore != null) { |
338 | | - DateTime nb = Util.parseDateTime(notBefore.getNodeValue()); |
339 | | - if (nb.isAfterNow()) { |
| 337 | + Node notBefore = subjectConfirmationDataNodes.item(c).getAttributes().getNamedItem("NotBefore"); |
| 338 | + if (notBefore != null) { |
| 339 | + DateTime nb = Util.parseDateTime(notBefore.getNodeValue()); |
| 340 | + if (nb.isAfterNow()) { |
340 | 341 | validationIssues.add(new SubjectConfirmationIssue(i, "SubjectConfirmationData is not yet valid")); |
341 | | - continue; |
| 342 | + continue; |
| 343 | + } |
| 344 | + } |
| 345 | + validSubjectConfirmation = true; |
342 | 346 | } |
343 | 347 | } |
344 | | - validSubjectConfirmation = true; |
345 | 348 | } |
346 | | - } |
347 | | - } |
348 | 349 |
|
349 | | - if (!validSubjectConfirmation) { |
| 350 | + if (!validSubjectConfirmation) { |
350 | 351 | throw new Exception(SubjectConfirmationIssue.prettyPrintIssues(validationIssues)); |
351 | 352 | } |
352 | 353 | } |
|
0 commit comments