</choice>\r
<attribute name="handlerURL" type="anyURI"/>\r
<attribute name="handlerSSL" type="boolean" default="true"/>\r
+ <attribute name="redirectErrors" type="anyURI"/>\r
<attribute name="cookieName" type="conf:string"/>\r
<attribute name="cookieProps" type="conf:string"/>\r
<attribute name="idpHistory" type="boolean" default="true"/>\r
<anyAttribute namespace="##other" processContents="lax"/>\r
</complexType>\r
</element>\r
+ \r
+ <attribute name="policyId" type="conf:string">
+ <annotation>
+ <documentation>Used to reference Policy elements from profile endpoints.</documentation>
+ </annotation>
+ </attribute>\r
+\r
<element name="SessionInitiator">\r
<annotation>\r
<documentation>Used to specify handlers that can issue AuthnRequests</documentation>\r
</sequence>\r
<attribute name="Location" type="anyURI" use="required"/>\r
<attribute name="Binding" type="anyURI" use="required"/>\r
+ <attribute name="id" type="conf:string"/>\r
+ <attribute name="isDefault" type="boolean"/>\r
<attribute name="wayfURL" type="anyURI"/>\r
<attribute name="wayfBinding" type="anyURI"/>\r
- <attribute name="isDefault" type="boolean"/>\r
- <attribute name="id" type="conf:string"/>\r
+ <attribute name="relayState" type="conf:string"/>\r
<anyAttribute namespace="##any" processContents="lax"/>\r
</complexType>\r
</element>\r
if (code && !XMLString::equals(code,saml2p::StatusCode::SUCCESS)) {
FatalProfileException ex("SAML Response message contained an error.");
auto_ptr_char c1(code);
- ex.addProperty("code", c1.get());
+ ex.addProperty("StatusCode", c1.get());
if (sc->getStatusCode()) {
code = sc->getStatusCode()->getValue();
auto_ptr_char c2(code);
- ex.addProperty("code2", c2.get());
+ ex.addProperty("StatusCode2", c2.get());
}
if (status->getStatusMessage()) {
auto_ptr_char msg(status->getStatusMessage()->getMessage());
- ex.addProperty("message", msg.get());
+ ex.addProperty("StatusMessage", msg.get());
}
}
}
const QName* code = sc ? sc->getValue() : NULL;
if (code && *code != saml1p::StatusCode::SUCCESS) {
FatalProfileException ex("SAML Response message contained an error.");
- ex.addProperty("code", code->toString().c_str());
+ ex.addProperty("StatusCode", code->toString().c_str());
if (sc->getStatusCode()) {
code = sc->getStatusCode()->getValue();
if (code)
- ex.addProperty("code2", code->toString().c_str());
+ ex.addProperty("StatusCode2", code->toString().c_str());
}
if (status->getStatusMessage()) {
auto_ptr_char msg(status->getStatusMessage()->getMessage());
- ex.addProperty("message", msg.get());
+ ex.addProperty("StatusMessage", msg.get());
}
}
}
pair<bool,long> AssertionConsumerService::run(SPRequest& request, bool isHandler) const
{
+ string relayState;
SPConfig& conf = SPConfig::getConfig();
- if (conf.isEnabled(SPConfig::OutOfProcess)) {
- // When out of process, we run natively and directly process the message.
- // RelayState will be fully handled during message processing.
- string relayState, providerId;
- string key = processMessage(request.getApplication(), request, providerId, relayState);
- return sendRedirect(request, key.c_str(), providerId.c_str(), relayState.c_str());
- }
- else {
- // When not out of process, we remote all the message processing.
- DDF in = wrap(request);
- DDFJanitor jin(in);
- in.addmember("application_id").string(request.getApplication().getId());
- DDF out=request.getServiceProvider().getListenerService()->send(in);
- DDFJanitor jout(out);
-
- // If it worked, we have a session key.
- if (!out["key"].isstring())
- throw FatalProfileException("Remote processing of SSO profile did not return a usable session key.");
+
+ try {
+ if (conf.isEnabled(SPConfig::OutOfProcess)) {
+ // When out of process, we run natively and directly process the message.
+ // RelayState will be fully handled during message processing.
+ string providerId;
+ string key = processMessage(request.getApplication(), request, providerId, relayState);
+ return sendRedirect(request, key.c_str(), providerId.c_str(), relayState.c_str());
+ }
+ else {
+ // When not out of process, we remote all the message processing.
+ DDF out,in = wrap(request);
+ DDFJanitor jin(in), jout(out);
+
+ in.addmember("application_id").string(request.getApplication().getId());
+ try {
+ out=request.getServiceProvider().getListenerService()->send(in);
+ }
+ catch (XMLToolingException& ex) {
+ // Try for RelayState recovery.
+ if (ex.getProperty("RelayState"))
+ relayState = ex.getProperty("RelayState");
+ try {
+ recoverRelayState(request, relayState);
+ }
+ catch (exception& ex2) {
+ m_log.error("trapped an error during RelayState recovery while handling an error: %s", ex2.what());
+ }
+ throw;
+ }
+
+ // We invoke RelayState recovery one last time on this side of the boundary.
+ if (out["RelayState"].isstring())
+ relayState = out["RelayState"].string();
+ recoverRelayState(request, relayState);
+
+ // If it worked, we have a session key.
+ if (!out["key"].isstring())
+ throw FatalProfileException("Remote processing of SSO profile did not return a usable session key.");
- // We invoke the RelayState method one last time on this side of the process boundary.
- string relayState;
- if (out["RelayState"].isstring())
- relayState = out["RelayState"].string();
- recoverRelayState(request, relayState);
- return sendRedirect(request, out["key"].string(), out["provider_id"].string(), relayState.c_str());
+ // Take care of cookie business and wrap it up.
+ return sendRedirect(request, out["key"].string(), out["provider_id"].string(), relayState.c_str());
+ }
+ }
+ catch (XMLToolingException& ex) {
+ // Try and preserve RelayState.
+ if (!relayState.empty())
+ ex.addProperty("RelayState", relayState.c_str());
+ throw;
}
}
// Do the work.
string relayState, providerId;
- string key = processMessage(*app, *http.get(), providerId, relayState);
-
- // Repack for return to caller.
- DDF ret=DDF(NULL).structure();
- DDFJanitor jret(ret);
- ret.addmember("key").string(key.c_str());
- if (!providerId.empty())
- ret.addmember("provider_id").string(providerId.c_str());
- if (!relayState.empty())
- ret.addmember("RelayState").string(relayState.c_str());
- out << ret;
+ try {
+ string key = processMessage(*app, *http.get(), providerId, relayState);
+
+ // Repack for return to caller.
+ DDF ret=DDF(NULL).structure();
+ DDFJanitor jret(ret);
+ ret.addmember("key").string(key.c_str());
+ if (!providerId.empty())
+ ret.addmember("provider_id").string(providerId.c_str());
+ if (!relayState.empty())
+ ret.addmember("RelayState").string(relayState.c_str());
+ out << ret;
+ }
+ catch (XMLToolingException& ex) {
+ // Try and preserve RelayState if we can.
+ if (!relayState.empty())
+ ex.addProperty("RelayState", relayState.c_str());
+ throw;
+ }
}
string AssertionConsumerService::processMessage(