From edf1819015ced8c0d56f0037003aec5aaf7cb9af Mon Sep 17 00:00:00 2001 From: Roland Hedberg Date: Fri, 25 Jan 2013 13:50:00 +0100 Subject: [PATCH] Final touch to ECP Worked through a NameIDMapping test --- setup.py | 2 +- src/saml2/client_base.py | 32 +++++++++++++++++++++----------- src/saml2/httpbase.py | 16 ++++++---------- src/saml2/pack.py | 1 + src/saml2/server.py | 2 +- src/saml2/soap.py | 4 ++++ tests/test_63_ecp.py | 7 ++++--- 7 files changed, 38 insertions(+), 26 deletions(-) diff --git a/setup.py b/setup.py index 6da5569..7287c74 100755 --- a/setup.py +++ b/setup.py @@ -37,7 +37,7 @@ class PyTest(Command): install_requires=[ # core dependencies 'decorator', - 'httplib2', + 'requests >= 1.0.0', 'paste', 'zope.interface', 'repoze.who == 1.0.18' diff --git a/src/saml2/client_base.py b/src/saml2/client_base.py index 14ace8b..082c9cb 100644 --- a/src/saml2/client_base.py +++ b/src/saml2/client_base.py @@ -18,7 +18,6 @@ """Contains classes and functions that a SAML2.0 Service Provider (SP) may use to conclude its tasks. """ -from saml2.schema import soapenv from saml2.entity import Entity from saml2.mdstore import destinations @@ -43,7 +42,7 @@ except ImportError: from saml2.s_utils import signature from saml2.s_utils import do_attributes -from saml2 import samlp, BINDING_SOAP, element_to_extension_element +from saml2 import samlp, BINDING_SOAP from saml2 import saml from saml2 import soap from saml2.population import Population @@ -468,7 +467,7 @@ class Base(Entity): # ======== response handling =========== - def parse_authn_request_response(self, xmlstr, binding, outstanding): + def parse_authn_request_response(self, xmlstr, binding, outstanding=None): """ Deal with an AuthnResponse :param xmlstr: The reply as a xml string @@ -564,7 +563,8 @@ class Base(Entity): # ------------------- ECP ------------------------------------------------ - def create_ecp_authn_request(self, entityid=None, relay_state="", sign=False): + def create_ecp_authn_request(self, entityid=None, relay_state="", + sign=False, **kwargs): """ Makes an authentication request. :param entityid: The entity ID of the IdP to send the request to @@ -596,14 +596,24 @@ class Base(Entity): # # ---------------------------------------- - logger.info("entityid: %s, binding: %s" % (entityid, BINDING_SOAP)) + try: + authn_req = kwargs["authn_req"] + except KeyError: + try: + _binding = kwargs["binding"] + except KeyError: + _binding = BINDING_SOAP + kwargs["binding"] = _binding - # The IDP publishes support for ECP by using the SOAP binding on - # SingleSignOnService - _, location = self.pick_binding("single_sign_on_service", - [BINDING_SOAP], entity_id=entityid) - authn_req = self.create_authn_request(location, binding=BINDING_SOAP, - service_url_binding=BINDING_PAOS) + logger.debug("entityid: %s, binding: %s" % (entityid, _binding)) + + # The IDP publishes support for ECP by using the SOAP binding on + # SingleSignOnService + _, location = self.pick_binding("single_sign_on_service", + [_binding], entity_id=entityid) + authn_req = self.create_authn_request(location, + service_url_binding=BINDING_PAOS, + **kwargs) # ---------------------------------------- # The SOAP envelope diff --git a/src/saml2/httpbase.py b/src/saml2/httpbase.py index 0930083..4b01647 100644 --- a/src/saml2/httpbase.py +++ b/src/saml2/httpbase.py @@ -7,7 +7,6 @@ import urlparse import requests import time from Cookie import SimpleCookie -from saml2.profile import paos from saml2.time_util import utc_now from saml2 import class_name from saml2.pack import http_form_post_message @@ -262,7 +261,7 @@ class HTTPBase(object): :param request: :param destination: - :param headers: + :param soap_headers: :param sign: :return: dictionary """ @@ -270,7 +269,7 @@ class HTTPBase(object): soap_message = make_soap_enveloped_saml_thingy(request, soap_headers) - logger.error("SOAP message: %s" % soap_message) + logger.debug("SOAP message: %s" % soap_message) if sign and self.sec: _signed = self.sec.sign_statement_using_xmlsec(soap_message, @@ -301,14 +300,11 @@ class HTTPBase(object): logger.info("HTTPClient exception: %s" % (exc,)) raise - if response: - if response.status_code == 200: - logger.info("SOAP response: %s" % response.text) - return response - else: - raise HTTPError("%d:%s" % (response.status_code, response.error)) + if response.status_code == 200: + logger.info("SOAP response: %s" % response.text) + return response else: - return None + raise HTTPError("%d:%s" % (response.status_code, response.error)) def add_credentials(self, user, passwd): self.user = user diff --git a/src/saml2/pack.py b/src/saml2/pack.py index 6bdc8c4..7f5d437 100644 --- a/src/saml2/pack.py +++ b/src/saml2/pack.py @@ -146,6 +146,7 @@ def make_soap_enveloped_saml_thingy(thingy, header_parts=None): header.tag = '{%s}Header' % NAMESPACE envelope.append(header) for part in header_parts: + # This doesn't work if the headers are signed part.become_child_element_of(header) body = ElementTree.Element('') diff --git a/src/saml2/server.py b/src/saml2/server.py index 8061c35..5b934dc 100644 --- a/src/saml2/server.py +++ b/src/saml2/server.py @@ -187,7 +187,7 @@ class Server(Entity): """ return self._parse_request(xml_string, NameIDMappingRequest, - "manage_name_id_service", binding) + "name_id_mapping_service", binding) # ------------------------------------------------------------------------ diff --git a/src/saml2/soap.py b/src/saml2/soap.py index e1f3f1a..e4bebcf 100644 --- a/src/saml2/soap.py +++ b/src/saml2/soap.py @@ -110,6 +110,10 @@ def parse_soap_enveloped_saml_authn_query_response(text): tags = ['{%s}Response' % SAMLP_NAMESPACE] return parse_soap_enveloped_saml_thingy(text, tags) +def parse_soap_enveloped_saml_authn_response(text): + tags = ['{%s}Response' % SAMLP_NAMESPACE] + return parse_soap_enveloped_saml_thingy(text, tags) + #def parse_soap_enveloped_saml_logout_response(text): # expected_tag = '{%s}LogoutResponse' % SAMLP_NAMESPACE diff --git a/tests/test_63_ecp.py b/tests/test_63_ecp.py index 09c7332..c60d8ea 100644 --- a/tests/test_63_ecp.py +++ b/tests/test_63_ecp.py @@ -98,7 +98,7 @@ def test_complete_flow(): idp = Server(config_file="idp_all_conf") IDP_ENTITY_ID = idp.config.entityid - SP_ENTITY_ID = sp.config.entityid + #SP_ENTITY_ID = sp.config.entityid # ------------ @Client ----------------------------- @@ -170,11 +170,12 @@ def test_complete_flow(): if item.c_tag == "Response" and item.c_namespace == ecp_prof.NAMESPACE: _ecp_response = item - _acs_url = _ecp_response.assertion_consumer_service_url + #_acs_url = _ecp_response.assertion_consumer_service_url # done phase2 at the client - ht_args = client.use_soap(idp_response, cargs["rc_url"], [cargs["relay_state"]]) + ht_args = client.use_soap(idp_response, cargs["rc_url"], + [cargs["relay_state"]]) print ht_args