diff --git a/shibsp/handler/AssertionConsumerService.h b/shibsp/handler/AssertionConsumerService.h index 45e8309..22fa143 100644 --- a/shibsp/handler/AssertionConsumerService.h +++ b/shibsp/handler/AssertionConsumerService.h @@ -112,7 +112,8 @@ namespace shibsp { const Application& application, const xmltooling::HTTPRequest& httpRequest, xmltooling::HTTPResponse& httpResponse, - std::string& relayState + std::string& relayState, + std::string session_id ) const; #ifndef SHIBSP_LITE @@ -150,7 +151,7 @@ namespace shibsp { * @param reserved ignore this parameter * @param xmlObject a protocol-specific message object */ - virtual void implementProtocol( + virtual std::string implementProtocol( const Application& application, const xmltooling::HTTPRequest& httpRequest, xmltooling::HTTPResponse& httpResponse, diff --git a/shibsp/handler/impl/AssertionConsumerService.cpp b/shibsp/handler/impl/AssertionConsumerService.cpp index 881e887..6448fc5 100644 --- a/shibsp/handler/impl/AssertionConsumerService.cpp +++ b/shibsp/handler/impl/AssertionConsumerService.cpp @@ -109,7 +109,7 @@ pair AssertionConsumerService::run(SPRequest& request, bool isHandler param = cgi.getParameters("target"); if (param.first != param.second && param.first->second) target = param.first->second; - return finalizeResponse(request.getApplication(), request, request, target); + return finalizeResponse(request.getApplication(), request, request, target, nullptr); } } @@ -184,7 +184,7 @@ pair AssertionConsumerService::processMessage( msg.reset(m_decoder->decode(relayState, httpRequest, *(policy.get()))); if (!msg) throw BindingException("Failed to decode an SSO protocol response."); - implementProtocol(application, httpRequest, httpResponse, *policy, nullptr, *msg); + string session_id = implementProtocol(application, httpRequest, httpResponse, *policy, nullptr, *msg); // History cookie. auto_ptr_char issuer(policy->getIssuer() ? policy->getIssuer()->getName() : nullptr); @@ -225,7 +225,7 @@ pair AssertionConsumerService::processMessage( return make_pair(true, httpResponse.sendRedirect(hook.c_str())); } - return finalizeResponse(application, httpRequest, httpResponse, relayState); + return finalizeResponse(application, httpRequest, httpResponse, relayState, session_id); } catch (XMLToolingException& ex) { // Recover relay state. @@ -295,23 +295,32 @@ pair AssertionConsumerService::processMessage( } pair AssertionConsumerService::finalizeResponse( - const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse, string& relayState + const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse, string& relayState, string session_id ) const { DDF postData = recoverPostData(application, httpRequest, httpResponse, relayState.c_str()); DDFJanitor postjan(postData); recoverRelayState(application, httpRequest, httpResponse, relayState); - application.limitRedirect(httpRequest, relayState.c_str()); + + string dest(relayState); + if (dest.find('?') == string::npos) + dest += '?'; + else + dest += '&'; + dest += "_shibsession_="; + dest += session_id; + + application.limitRedirect(httpRequest, dest.c_str()); // 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())); + m_log.debug("ACS returning via redirect to: %s", dest.c_str()); + return make_pair(true, httpResponse.sendRedirect(dest.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)); + m_log.debug("ACS returning via POST to: %s", dest.c_str()); + return make_pair(true, sendPostResponse(application, httpResponse, dest.c_str(), postData)); } } diff --git a/shibsp/handler/impl/SAML1Consumer.cpp b/shibsp/handler/impl/SAML1Consumer.cpp index 0b663a2..98c8b97 100644 --- a/shibsp/handler/impl/SAML1Consumer.cpp +++ b/shibsp/handler/impl/SAML1Consumer.cpp @@ -89,7 +89,7 @@ namespace shibsp { } private: - void implementProtocol( + string implementProtocol( const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse, @@ -132,7 +132,7 @@ namespace shibsp { #ifndef SHIBSP_LITE -void SAML1Consumer::implementProtocol( +string SAML1Consumer::implementProtocol( const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse, @@ -353,6 +353,7 @@ void SAML1Consumer::implementProtocol( login_event->m_attributes = &ctx->getResolvedAttributes(); application.getServiceProvider().getTransactionLog()->write(*login_event); } + return session_id; } #endif diff --git a/shibsp/handler/impl/SAML2Consumer.cpp b/shibsp/handler/impl/SAML2Consumer.cpp index ec62384..d525e0f 100644 --- a/shibsp/handler/impl/SAML2Consumer.cpp +++ b/shibsp/handler/impl/SAML2Consumer.cpp @@ -86,7 +86,7 @@ namespace shibsp { } private: - void implementProtocol( + string implementProtocol( const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse, @@ -128,7 +128,7 @@ namespace shibsp { #ifndef SHIBSP_LITE -void SAML2Consumer::implementProtocol( +string SAML2Consumer::implementProtocol( const Application& application, const HTTPRequest& httpRequest, HTTPResponse& httpResponse, @@ -493,6 +493,7 @@ void SAML2Consumer::implementProtocol( catch (std::exception& ex) { m_log.warn("exception auditing event: %s", ex.what()); } + return session_id; } #endif diff --git a/shibsp/impl/StorageServiceSessionCache.cpp b/shibsp/impl/StorageServiceSessionCache.cpp index 9e5d48d..b381f5e 100644 --- a/shibsp/impl/StorageServiceSessionCache.cpp +++ b/shibsp/impl/StorageServiceSessionCache.cpp @@ -165,6 +165,16 @@ namespace { } pair shib_cookie = app.getCookieNameProps("_shibsession_"); const char* session_id = request.getCookie(shib_cookie.first.c_str()); + if (!session_id) { + // try to find it in url + const char* query = request.getQueryString(); + + session_id = query ? strstr(query, "_shibsession_=") : nullptr; + if (session_id) { + session_id += strlen("_shibsession_="); + m_log.warn("found session_id %s in url", session_id); + } + } return (session_id ? session_id : ""); }