- // Now redirect to the state value. By now, it should be set to *something* usable.
- // First check for POST data.
- if (!postData.islist()) {
- m_log.debug("ACS returning via redirect to: %s", relayState.c_str());
- return make_pair(true, httpResponse.sendRedirect(relayState.c_str()));
- }
- else {
- m_log.debug("ACS returning via POST to: %s", relayState.c_str());
- return make_pair(true, sendPostResponse(application, httpResponse, relayState.c_str(), postData));
+ const EntityDescriptor* entity =
+ dynamic_cast<const EntityDescriptor*>(policy->getIssuerMetadata() ? policy->getIssuerMetadata()->getParent() : nullptr);
+ prop = application.getRelyingParty(entity)->getString("sessionHook");
+ if (prop.first) {
+ string hook(prop.second);
+ httpRequest.absolutize(hook);
+
+ // Compute the return URL. We use a self-referential link plus a hook indicator to break the cycle
+ // and the relay state.
+ const URLEncoder* encoder = XMLToolingConfig::getConfig().getURLEncoder();
+ string returnURL = httpRequest.getRequestURL();
+ returnURL = returnURL.substr(0, returnURL.find('?')) + "?hook=1";
+ if (!relayState.empty())
+ returnURL += "&target=" + encoder->encode(relayState.c_str());
+ if (hook.find('?') == string::npos)
+ hook += '?';
+ else
+ hook += '&';
+ hook += "return=" + encoder->encode(returnURL.c_str());
+
+ // Add the translated target resource in case it's of interest.
+ if (!relayState.empty()) {
+ try {
+ recoverRelayState(application, httpRequest, httpResponse, relayState, false);
+ hook += "&target=" + encoder->encode(relayState.c_str());
+ }
+ catch (std::exception& ex) {
+ m_log.warn("error recovering relay state: %s", ex.what());
+ }
+ }
+
+ return make_pair(true, httpResponse.sendRedirect(hook.c_str()));