From 9be4b519723e188d5b4dc5c52ed39d5d1e377d41 Mon Sep 17 00:00:00 2001 From: Scott Cantor Date: Wed, 19 Dec 2007 23:18:32 +0000 Subject: [PATCH] Add return parameter and relay state support to logout processing in lieu of templates. --- configs/shibboleth2.xml.in | 2 +- schemas/shibboleth-2.0-native-sp-config.xsd | 1 + shibsp/handler/impl/LocalLogoutInitiator.cpp | 4 ++++ shibsp/handler/impl/LogoutHandler.cpp | 10 +++++++++- shibsp/handler/impl/SAML2Logout.cpp | 6 ++++++ shibsp/handler/impl/SAML2LogoutInitiator.cpp | 15 ++++++++++++++- 6 files changed, 35 insertions(+), 3 deletions(-) diff --git a/configs/shibboleth2.xml.in b/configs/shibboleth2.xml.in index c7ac88a..bd35126 100644 --- a/configs/shibboleth2.xml.in +++ b/configs/shibboleth2.xml.in @@ -143,7 +143,7 @@ Binding="urn:oasis:names:tc:SAML:1.0:profiles:artifact-01"/> - + diff --git a/schemas/shibboleth-2.0-native-sp-config.xsd b/schemas/shibboleth-2.0-native-sp-config.xsd index c08d2b4..fb2d538 100644 --- a/schemas/shibboleth-2.0-native-sp-config.xsd +++ b/schemas/shibboleth-2.0-native-sp-config.xsd @@ -569,6 +569,7 @@ + diff --git a/shibsp/handler/impl/LocalLogoutInitiator.cpp b/shibsp/handler/impl/LocalLogoutInitiator.cpp index 832e640..6850bec 100644 --- a/shibsp/handler/impl/LocalLogoutInitiator.cpp +++ b/shibsp/handler/impl/LocalLogoutInitiator.cpp @@ -109,5 +109,9 @@ pair LocalLogoutInitiator::run(SPRequest& request, bool isHandler) co request.getServiceProvider().getSessionCache()->remove(app, request, &request); } + // Route back to return location specified, or use the local template. + const char* dest = request.getParameter("return"); + if (dest) + return make_pair(true, request.sendRedirect(dest)); return sendLogoutPage(app, request, request, true, "Logout was successful."); } diff --git a/shibsp/handler/impl/LogoutHandler.cpp b/shibsp/handler/impl/LogoutHandler.cpp index c86b412..5342397 100644 --- a/shibsp/handler/impl/LogoutHandler.cpp +++ b/shibsp/handler/impl/LogoutHandler.cpp @@ -119,6 +119,9 @@ pair LogoutHandler::notifyFrontChannel( if (param) index = atoi(param); + // "return" is a backwards-compatible "eventual destination" to go back to after logout completes. + param = request.getParameter("return"); + // Fetch the next front notification URL and bump the index for the next round trip. string loc = application.getNotificationURL(request.getRequestURL(), true, index++); if (loc.empty()) @@ -138,6 +141,10 @@ pair LogoutHandler::notifyFrontChannel( // Add a signal that we're coming back from notification and the next index. locstr << "?notifying=1&index=" << index; + // Add return if set. + if (param) + locstr << "&return=" << encoder->encode(param); + // We preserve anything we're instructed to directly. if (params) { for (map::const_iterator p = params->begin(); p!=params->end(); ++p) @@ -151,7 +158,8 @@ pair LogoutHandler::notifyFrontChannel( } } - // Add the return parameter to the destination location and redirect. + // Add the notifier's return parameter to the destination location and redirect. + // This is NOT the same as the return parameter that might be embedded inside it ;-) loc = loc + "&return=" + encoder->encode(locstr.str().c_str()); return make_pair(true,response.sendRedirect(loc.c_str())); } diff --git a/shibsp/handler/impl/SAML2Logout.cpp b/shibsp/handler/impl/SAML2Logout.cpp index ade83f0..7dd1d78 100644 --- a/shibsp/handler/impl/SAML2Logout.cpp +++ b/shibsp/handler/impl/SAML2Logout.cpp @@ -514,6 +514,12 @@ pair SAML2Logout::doRequest(const Application& application, const HTT } checkError(logoutResponse, policy.getIssuerMetadata()); // throws if Status doesn't look good... + // If relay state is set, recover the original return URL. + if (!relayState.empty()) + recoverRelayState(application, request, response, relayState); + if (!relayState.empty()) + return make_pair(true, response.sendRedirect(relayState.c_str())); + // Return template for completion of global logout, or redirect to homeURL. return sendLogoutPage(application, request, response, false, "Global logout completed."); } diff --git a/shibsp/handler/impl/SAML2LogoutInitiator.cpp b/shibsp/handler/impl/SAML2LogoutInitiator.cpp index 00a1a66..ff813d3 100644 --- a/shibsp/handler/impl/SAML2LogoutInitiator.cpp +++ b/shibsp/handler/impl/SAML2LogoutInitiator.cpp @@ -348,6 +348,11 @@ pair SAML2LogoutInitiator::doRequest( } else { delete logoutResponse; + const char* returnloc = httpRequest.getParameter("return"); + if (returnloc) { + ret.second = httpResponse.sendRedirect(returnloc); + ret.first = true; + } ret = sendLogoutPage(application, httpRequest, httpResponse, false, "Logout completed successfully."); } @@ -359,11 +364,19 @@ pair SAML2LogoutInitiator::doRequest( return ret; } + // Save off return location as RelayState. + string relayState; + const char* returnloc = httpRequest.getParameter("return"); + if (returnloc) { + relayState = returnloc; + preserveRelayState(application, httpResponse, relayState); + } + auto_ptr msg(buildRequest(application, *session, *role, encoder)); msg->setDestination(ep->getLocation()); auto_ptr_char dest(ep->getLocation()); - ret.second = sendMessage(*encoder, msg.get(), NULL, dest.get(), role, application, httpResponse); + ret.second = sendMessage(*encoder, msg.get(), relayState.c_str(), dest.get(), role, application, httpResponse); ret.first = true; msg.release(); // freed by encoder } -- 2.1.4