Skip to content

Commit ca9d5f2

Browse files
authored
Merge pull request #351 from mauromol/improve-response-status-in-logout-response
Support more complex response statuses in LogoutResponse generation
2 parents 38f3480 + 07044ad commit ca9d5f2

File tree

2 files changed

+81
-42
lines changed

2 files changed

+81
-42
lines changed

core/src/main/java/com/onelogin/saml2/logout/LogoutResponse.java

Lines changed: 56 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -353,37 +353,48 @@ protected NodeList query (String query) throws XPathExpressionException {
353353
return Util.query(this.logoutResponseDocument, query, null);
354354
}
355355

356-
/**
357-
* Generates a Logout Response XML string.
358-
*
359-
* @param inResponseTo
360-
* InResponseTo attribute value to bet set at the Logout Response.
361-
* @param statusCode
362-
* String StatusCode to be set on the LogoutResponse
363-
*/
364-
public void build(String inResponseTo, String statusCode) {
356+
/**
357+
* Generates a Logout Response XML string.
358+
*
359+
* @param inResponseTo
360+
* InResponseTo attribute value to bet set at the Logout Response.
361+
* @param responseStatus
362+
* SamlResponseStatus response status to be set on the LogoutResponse
363+
*/
364+
public void build(String inResponseTo, SamlResponseStatus responseStatus) {
365365
id = Util.generateUniqueID(settings.getUniqueIDPrefix());
366366
issueInstant = Calendar.getInstance();
367367
this.inResponseTo = inResponseTo;
368368

369-
StrSubstitutor substitutor = generateSubstitutor(settings, statusCode);
369+
StrSubstitutor substitutor = generateSubstitutor(settings, responseStatus);
370370
this.logoutResponseString = postProcessXml(substitutor.replace(getLogoutResponseTemplate()), settings);
371371
}
372372

373-
/**
374-
* Generates a Logout Response XML string.
375-
*
376-
* @param inResponseTo
377-
* InResponseTo attribute value to bet set at the Logout Response.
378-
*/
373+
/**
374+
* Generates a Logout Response XML string.
375+
*
376+
* @param inResponseTo
377+
* InResponseTo attribute value to bet set at the Logout Response.
378+
* @param statusCode
379+
* String StatusCode to be set on the LogoutResponse
380+
*/
381+
public void build(String inResponseTo, String statusCode) {
382+
build(inResponseTo, new SamlResponseStatus(statusCode));
383+
}
384+
385+
/**
386+
* Generates a Logout Response XML string.
387+
*
388+
* @param inResponseTo
389+
* InResponseTo attribute value to bet set at the Logout Response.
390+
*/
379391
public void build(String inResponseTo) {
380392
build(inResponseTo, Constants.STATUS_SUCCESS);
381393
}
382394

383-
/**
384-
* Generates a Logout Response XML string.
385-
*
386-
*/
395+
/**
396+
* Generates a Logout Response XML string.
397+
*/
387398
public void build() {
388399
build(null);
389400
}
@@ -413,12 +424,12 @@ protected String postProcessXml(final String logoutResponseXml, final Saml2Setti
413424
*
414425
* @param settings
415426
* Saml2Settings object. Setting data
416-
* @param statusCode
417-
* String StatusCode to be set on the LogoutResponse
427+
* @param responseStatus
428+
* SamlResponseStatus response status to be set on the LogoutResponse
418429
*
419430
* @return the StrSubstitutor object of the LogoutResponse
420431
*/
421-
private StrSubstitutor generateSubstitutor(Saml2Settings settings, String statusCode) {
432+
private StrSubstitutor generateSubstitutor(Saml2Settings settings, SamlResponseStatus responseStatus) {
422433
Map<String, String> valueMap = new HashMap<String, String>();
423434

424435
valueMap.put("id", Util.toXml(id));
@@ -439,29 +450,34 @@ private StrSubstitutor generateSubstitutor(Saml2Settings settings, String status
439450
}
440451
valueMap.put("inResponseStr", inResponseStr);
441452

442-
String statusStr = "";
443-
if (statusCode != null) {
444-
statusStr = "Value=\"" + Util.toXml(statusCode) + "\"";
453+
StringBuilder statusStr = new StringBuilder("<samlp:StatusCode ");
454+
if (responseStatus != null) {
455+
String statusCode = responseStatus.getStatusCode();
456+
if (statusCode != null) {
457+
statusStr.append("Value=\"").append(Util.toXml(statusCode)).append("\"");
458+
String subStatusCode = responseStatus.getSubStatusCode();
459+
if (subStatusCode != null) {
460+
statusStr.append("><samlp:StatusCode Value=\"")
461+
.append(Util.toXml(subStatusCode))
462+
.append("\" /></samlp:StatusCode>");
463+
} else {
464+
statusStr.append(" />");
465+
}
466+
String statusMessage = responseStatus.getStatusMessage();
467+
if (statusMessage != null) {
468+
statusStr.append("<samlp:StatusMessage>")
469+
.append(Util.toXml(statusMessage))
470+
.append("</samlp:StatusMessage>");
471+
}
472+
}
445473
}
446-
valueMap.put("statusStr", statusStr);
474+
valueMap.put("statusStr", statusStr.toString());
447475

448476
valueMap.put("issuer", Util.toXml(settings.getSpEntityId()));
449477

450478
return new StrSubstitutor(valueMap);
451479
}
452480

453-
/**
454-
* Substitutes LogoutResponse variables within a string by values.
455-
*
456-
* @param settings
457-
* Saml2Settings object. Setting data
458-
*
459-
* @return the StrSubstitutor object of the LogoutResponse
460-
*/
461-
private StrSubstitutor generateSubstitutor(Saml2Settings settings) {
462-
return generateSubstitutor(settings, Constants.STATUS_SUCCESS);
463-
}
464-
465481
/**
466482
* @return the LogoutResponse's template
467483
*/
@@ -473,7 +489,7 @@ private static StringBuilder getLogoutResponseTemplate() {
473489
template.append("IssueInstant=\"${issueInstant}\"${destinationStr}${inResponseStr} >");
474490
template.append("<saml:Issuer>${issuer}</saml:Issuer>");
475491
template.append("<samlp:Status>");
476-
template.append("<samlp:StatusCode ${statusStr} />");
492+
template.append("${statusStr}");
477493
template.append("</samlp:Status>");
478494
template.append("</samlp:LogoutResponse>");
479495
return template;

core/src/test/java/com/onelogin/saml2/test/logout/LogoutResponseTest.java

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import com.onelogin.saml2.exception.XMLEntityException;
2525
import com.onelogin.saml2.http.HttpRequest;
2626
import com.onelogin.saml2.logout.LogoutResponse;
27+
import com.onelogin.saml2.model.SamlResponseStatus;
2728
import com.onelogin.saml2.settings.Saml2Settings;
2829
import com.onelogin.saml2.settings.SettingsBuilder;
2930
import com.onelogin.saml2.test.NaiveUrlEncoder;
@@ -162,12 +163,34 @@ public void testBuild() throws IOException, XMLEntityException, URISyntaxExcepti
162163
assertThat(logoutRequestStr, containsString("StatusCode Value=\"urn:oasis:names:tc:SAML:2.0:status:Success\""));
163164

164165
LogoutResponse logoutResponse3 = new LogoutResponse(settings, httpRequest);
165-
logoutResponse3.build("inResponseValue", Constants.STATUS_REQUEST_DENIED);
166+
logoutResponse3.build("inResponseValue", Constants.STATUS_VERSION_MISMATCH);
166167
logoutRequestStringBase64 = logoutResponse3.getEncodedLogoutResponse();
167168
logoutRequestStr = Util.base64decodedInflated(logoutRequestStringBase64);
168169
assertThat(logoutRequestStr, containsString("<samlp:LogoutResponse"));
169170
assertThat(logoutRequestStr, containsString("InResponseTo=\"inResponseValue\""));
170-
assertThat(logoutRequestStr, containsString("StatusCode Value=\"" + Constants.STATUS_REQUEST_DENIED + "\""));
171+
assertThat(logoutRequestStr, containsString("<samlp:StatusCode Value=\"" + Constants.STATUS_VERSION_MISMATCH + "\" />"));
172+
assertThat(logoutRequestStr, not(containsString("</samlp:StatusCode>")));
173+
assertThat(logoutRequestStr, not(containsString("<samlp:StatusMessage>")));
174+
175+
LogoutResponse logoutResponse4 = new LogoutResponse(settings, httpRequest);
176+
SamlResponseStatus responseStatus = new SamlResponseStatus(Constants.STATUS_RESPONDER);
177+
responseStatus.setSubStatusCode(Constants.STATUS_PARTIAL_LOGOUT);
178+
logoutResponse4.build("inResponseValue", responseStatus);
179+
logoutRequestStringBase64 = logoutResponse4.getEncodedLogoutResponse();
180+
logoutRequestStr = Util.base64decodedInflated(logoutRequestStringBase64);
181+
assertThat(logoutRequestStr, containsString("<samlp:LogoutResponse"));
182+
assertThat(logoutRequestStr, containsString("InResponseTo=\"inResponseValue\""));
183+
assertThat(logoutRequestStr, containsString("<samlp:StatusCode Value=\"" + Constants.STATUS_RESPONDER + "\"><samlp:StatusCode Value=\"" + Constants.STATUS_PARTIAL_LOGOUT + "\" /></samlp:StatusCode>"));
184+
assertThat(logoutRequestStr, not(containsString("<samlp:StatusMessage>")));
185+
186+
responseStatus.setStatusMessage("status message");
187+
logoutResponse4.build("inResponseValue", responseStatus);
188+
logoutRequestStringBase64 = logoutResponse4.getEncodedLogoutResponse();
189+
logoutRequestStr = Util.base64decodedInflated(logoutRequestStringBase64);
190+
assertThat(logoutRequestStr, containsString("<samlp:LogoutResponse"));
191+
assertThat(logoutRequestStr, containsString("InResponseTo=\"inResponseValue\""));
192+
assertThat(logoutRequestStr, containsString("<samlp:StatusCode Value=\"" + Constants.STATUS_RESPONDER + "\"><samlp:StatusCode Value=\"" + Constants.STATUS_PARTIAL_LOGOUT + "\" /></samlp:StatusCode>"));
193+
assertThat(logoutRequestStr, containsString("<samlp:StatusMessage>status message</samlp:StatusMessage>"));
171194
}
172195

173196
/**

0 commit comments

Comments
 (0)