Open jbasney opened 9 years ago
https://tools.ietf.org/html/draft-ietf-kitten-sasl-saml-ec-13 includes a new urn:ietf:params:xml:ns:samlec Binding which is recommended instead of urn:oasis:names:tc:SAML:2.0:bindings:PAOS.
Using the new binding should fix #17 as well.
Switch from enctype names to numbers done in 9ac62a7f48e7beaa210d526c610558847f9d4584.
Looks like the IdP also has to support the new binding. If I remove the ProtocolBinding from the AuthnRequest that mech_saml_ec issues, the IdP logs this error:
09:49:59.852 - WARN [org.opensaml.saml2.binding.AuthnResponseEndpointSelector:206] - Relying party 'https://fedushare-dev-sp.vagrant.dev/shibboleth' requested the response to be returned to endpoint with ACS URL 'host@fedushare-dev-sp.vagrant.dev' and binding 'urn:ietf:params:xml:ns:samlec' however no endpoint, with that URL and using a supported binding, can be found in the relying party's metadata
09:49:59.852 - ERROR [edu.internet2.middleware.shibboleth.idp.profile.AbstractSAMLProfileHandler:447] - No return endpoint available for relying party https://fedushare-dev-sp.vagrant.dev/shibboleth
09:49:59.852 - DEBUG [edu.internet2.middleware.shibboleth.idp.profile.saml2.SAML2ECPProfileHandler:278] - Returning SOAP fault
edu.internet2.middleware.shibboleth.common.profile.ProfileException: No peer endpoint available to which to send SAML response
...
Looking at the code for the AbstractSAMLProfileHandler class, the class has a method getSupportedIssuerBindings
. The IdP looks for an ACS with a binding that is in that list.
The IdP doesn't necessarily need to support the new binding, since it should still work with the old binding. Since there is no longer a ProtocolBinding on the SAML AuthnRequest in the spec, I think the only change that needs to happen is that the library checks that the SP has an ACS configured with (Binding="urn:ietf:params:xml:ns:samlec" or Binding="urn:oasis:names:tc:SAML:2.0:bindings:PAOS") and Location="host@
The IdP then requires an ACS in the SP's metadata with Location="host@
So now, how to get the SP to recognize that it has an additional ACS? For the IdP, we can just add a line to the SP metadata before uploading it.
According to the documentation, you can add an AssertionConsumerService element to the Sessions element in /etc/shibboleth/shibboleth2.xml
. However, when I try that, the new ACS isn't included in the list of all handlers.
According to the Sessions documentation, in SP 2.4+, the SSO element replaces SessionInitiator and AssertionConsumerService in the Sessions configuration. SSO's documentation says you can add support for non-standard/non-browser protocols through a ProtocolProvider plugin interface, but I don't see documentation for ProtocolProvider. The Sessions documentation also says "You can still plugin all of the older information by hand if you need unusual settings or more control over the internals. It's best to replace the new elements entirely to avoid unforeseen overlaps and interactions."
The SP cannot be configured to recognize an ACS with the new binding without support for it in the SP code. From shibsp/impl/XMLServiceProvider.cpp
:
if (XMLString::equals(child->getLocalName(), _AssertionConsumerService)) {
string bindprop(XMLHelper::getAttrString(child, nullptr, Binding));
if (bindprop.empty()) {
log.error("AssertionConsumerService element has no Binding attribute, skipping it...");
child = XMLHelper::getNextSiblingElement(child);
continue;
}
handler.reset(conf.AssertionConsumerServiceManager.newPlugin(bindprop.c_str(), pair<const DOMElement*,const char*>(child, getId())));
Currently, conf.AssertionConsumerServiceManager.newPlugin(bindprop.c_str() ...
throws an exception when attempting to configure an ACS with the samlec
binding.
shibsp/handler/impl/AbstractHandler
contains:
conf.AssertionConsumerServiceManager.registerFactory(SAML1_ASSERTION_CONSUMER_SERVICE, SAML1ConsumerFactory); conf.AssertionConsumerServiceManager.registerFactory(SAML1_PROFILE_BROWSER_ARTIFACT, SAML1ConsumerFactory);
conf.AssertionConsumerServiceManager.registerFactory(SAML1_PROFILE_BROWSER_POST, SAML1ConsumerFactory);
conf.AssertionConsumerServiceManager.registerFactory(SAML20_ASSERTION_CONSUMER_SERVICE, SAML2ConsumerFactory);
conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_HTTP_POST, SAML2ConsumerFactory);
conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_HTTP_POST_SIMPLESIGN, SAML2ConsumerFactory);
conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_HTTP_ARTIFACT, SAML2ConsumerFactory);
conf.AssertionConsumerServiceManager.registerFactory(SAML20_BINDING_PAOS, SAML2ConsumerFactory);
So there would need to be a call to register SAML2ConsumerFactory
for the samlec
binding as well. I think this could be provided through an SP plugin.
Then again... it looks like the SP will not support an ECP request using a non PAOS binding.
See line 276 of shibsp/handler/impl/SAML2SessionInitiator.cpp
https://tools.ietf.org/html/draft-ietf-kitten-sasl-saml-ec-12 includes a change to use enctype numbers instead of names (diff).