From 47c7dc6fe1a34f64f096b262305d05657ec0ea5c Mon Sep 17 00:00:00 2001 From: ktreimann Date: Thu, 16 Sep 2021 12:14:00 -0400 Subject: [PATCH] Fix for LogoutRequest to ADFS - ADFS would not accept the LogoutRequest without a Destination attribute - If an Assertion Subject NameID had a Format, the Format must be included in the LogoutRequest in order to match the principal at the IDP - The SessionIndex should be included in the LogoutRequest to terminate the correct session - Added a redirectToIdentityProvider method to capture this additional information --- src/main/java/com/coveo/saml/SamlClient.java | 50 +++++++++++++++++++- 1 file changed, 49 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/coveo/saml/SamlClient.java b/src/main/java/com/coveo/saml/SamlClient.java index 5b03fa4..21d5020 100644 --- a/src/main/java/com/coveo/saml/SamlClient.java +++ b/src/main/java/com/coveo/saml/SamlClient.java @@ -60,6 +60,7 @@ import org.opensaml.saml.saml2.core.NameIDPolicy; import org.opensaml.saml.saml2.core.RequestAbstractType; import org.opensaml.saml.saml2.core.Response; +import org.opensaml.saml.saml2.core.SessionIndex; import org.opensaml.saml.saml2.core.Status; import org.opensaml.saml.saml2.core.StatusCode; import org.opensaml.saml.saml2.core.StatusMessage; @@ -796,11 +797,39 @@ public String getSamlRequest() throws SamlException { * @throws SamlException the saml exception */ public String getLogoutRequest(String nameId) throws SamlException { + return getLogoutRequest(nameId, null, null, null); + } + + /** + * Gets the encoded logout request, optionally including + * additional details about the user and session. + * + * @param nameId the name id + * @param nameIdFormat Optional format used for the name id + * @param sessionIndex Optional session to be terminated + * @param destination Optional URI of the destination of the request + * @return the logout request + * @throws SamlException if signing fails, or if marshalling the request fails + */ + public String getLogoutRequest( + String nameId, String nameIdFormat, String sessionIndex, String destination) + throws SamlException { LogoutRequest request = (LogoutRequest) getBasicSamlRequest(LogoutRequest.DEFAULT_ELEMENT_NAME); NameID nid = (NameID) buildSamlObject(NameID.DEFAULT_ELEMENT_NAME); nid.setValue(nameId); + if (nameIdFormat != null) { + nid.setFormat(nameIdFormat); + } request.setNameID(nid); + if (sessionIndex != null) { + SessionIndex element = (SessionIndex) buildSamlObject(SessionIndex.DEFAULT_ELEMENT_NAME); + element.setSessionIndex(sessionIndex); + request.getSessionIndexes().add(element); + } + if (destination != null) { + request.setDestination(destination); + } signSAMLObject(request); @@ -897,8 +926,27 @@ public SamlLogoutResponse processPostLogoutResponseFromIdentityProvider( public void redirectToIdentityProvider( HttpServletResponse response, String relayState, String nameId) throws IOException, SamlException { + redirectToIdentityProvider(response, relayState, nameId, null, null, null); + } + /** + * Redirects an {@link HttpServletResponse} to the configured identity provider, + * including additional details to be sent to the IDP (required by ADFS). + * + * @param response The {@link HttpServletResponse}. + * @param relayState Optional relay state that will be passed along. + * @param nameId the user to log out. + * @param nameIdFormat the format used for the NameID (if required). + * @param sessionIndex the session to be terminated. + * @param destination the IDP logout URL. + * @throws IOException thrown if an IO error occurs. + * @throws SamlException thrown is an unexpected error occurs. + */ + public void redirectToIdentityProvider( + HttpServletResponse response, String relayState, String nameId, + String nameIdFormat, String sessionIndex, String destination) + throws IOException, SamlException { Map values = new HashMap<>(); - values.put("SAMLRequest", getLogoutRequest(nameId)); + values.put("SAMLRequest", getLogoutRequest(nameId, nameIdFormat, sessionIndex, destination)); if (relayState != null) { values.put("RelayState", relayState); }