diff --git a/src/saml2/ecp.py b/src/saml2/ecp.py index f15a259..5817cda 100644 --- a/src/saml2/ecp.py +++ b/src/saml2/ecp.py @@ -24,6 +24,8 @@ from saml2.schema import soapenv from saml2.response import authn_response +from saml2 import saml + logger = logging.getLogger(__name__) @@ -53,7 +55,7 @@ def ecp_auth_request(cls, entityid=None, relay_state="", sign=False): # ---------------------------------------- # # ---------------------------------------- - my_url = cls.service_url(BINDING_PAOS) + my_url = cls.service_urls(BINDING_PAOS)[0] # must_understand and actor according to the standard # @@ -63,38 +65,6 @@ def ecp_auth_request(cls, entityid=None, relay_state="", sign=False): eelist.append(element_to_extension_element(paos_request)) - # ---------------------------------------- - # - # ---------------------------------------- - -# idp = samlp.IDPEntry( -# provider_id = "https://idp.example.org/entity", -# name = "Example identity provider", -# loc = "https://idp.example.org/saml2/sso", -# ) -# -# idp_list = samlp.IDPList(idp_entry= [idp]) -# -# ecp_request = ecp.Request( -# actor = ACTOR, must_understand = "1", -# provider_name = "Example Service Provider", -# issuer=saml.Issuer(text="https://sp.example.org/entity"), -# idp_list = idp_list) -# -# eelist.append(element_to_extension_element(ecp_request)) - - # ---------------------------------------- - # - # ---------------------------------------- - - relay_state = ecp.RelayState(actor=ACTOR, must_understand="1", - text=relay_state) - - eelist.append(element_to_extension_element(relay_state)) - - header = soapenv.Header() - header.extension_elements = eelist - # ---------------------------------------- # # ---------------------------------------- @@ -108,6 +78,40 @@ def ecp_auth_request(cls, entityid=None, relay_state="", sign=False): body = soapenv.Body() body.extension_elements = [element_to_extension_element(authn_req)] + # ---------------------------------------- + # + # ---------------------------------------- + +# idp = samlp.IDPEntry( +# provider_id = "https://idp.example.org/entity", +# name = "Example identity provider", +# loc = "https://idp.example.org/saml2/sso", +# ) +# +# idp_list = samlp.IDPList(idp_entry= [idp]) + + idp_list = None + ecp_request = ecp.Request( + actor=ACTOR, + must_understand="1", + provider_name=None, + issuer=saml.Issuer(text=authn_req.issuer.text), + idp_list=idp_list) + + eelist.append(element_to_extension_element(ecp_request)) + + # ---------------------------------------- + # + # ---------------------------------------- + + relay_state = ecp.RelayState(actor=ACTOR, must_understand="1", + text=relay_state) + + eelist.append(element_to_extension_element(relay_state)) + + header = soapenv.Header() + header.extension_elements = eelist + # ---------------------------------------- # The SOAP envelope # ---------------------------------------- @@ -126,7 +130,7 @@ def handle_ecp_authn_response(cls, soap_message, outstanding=None): if item.c_tag == "RelayState" and item.c_namespace == ecp.NAMESPACE: _relay_state = item - response = authn_response(cls.config, cls.service_url(), outstanding, + response = authn_response(cls.config, cls.service_urls(), outstanding, allow_unsolicited=True) response.loads("%s" % rdict["body"], False, soap_message) diff --git a/src/saml2/ecp_client.py b/src/saml2/ecp_client.py index 90c3b44..788d252 100644 --- a/src/saml2/ecp_client.py +++ b/src/saml2/ecp_client.py @@ -119,7 +119,7 @@ class Client(Entity): if response.status_code != 200: raise SAMLError( "Request to IdP failed (%s): %s" % (response.status_code, - response.error)) + response.text)) # SAMLP response in a SOAP envelope body, ecp response in headers respdict = self.parse_soap_message(response.text) @@ -200,22 +200,19 @@ class Client(Entity): ht_args = self.use_soap(idp_response, args["rc_url"], [args["relay_state"]]) - + ht_args["headers"][0] = ('Content-Type', MIME_PAOS) logger.debug("[P3] Post to SP: %s", ht_args["data"]) - ht_args["headers"].append(('Content-Type', 'application/vnd.paos+xml')) - # POST the package from the IdP to the SP - response = self.send(args["rc_url"], "POST", **ht_args) + response = self.send(**ht_args) if response.status_code == 302: # ignore where the SP is redirecting us to and go for the # url I started off with. pass else: - print(response.error) raise SAMLError( - "Error POSTing package to SP: %s" % response.error) + "Error POSTing package to SP: %s" % response.text) logger.debug("[P3] SP response: %s", response.text) @@ -255,8 +252,7 @@ class Client(Entity): :param opargs: Arguments to the HTTP call :return: The page """ - if url not in opargs: - url = self._sp + sp_url = self._sp # ******************************************** # Phase 1 - First conversation with the SP @@ -264,13 +260,13 @@ class Client(Entity): # headers needed to indicate to the SP that I'm ECP enabled opargs["headers"] = self.add_paos_headers(opargs["headers"]) - - response = self.send(url, op, **opargs) - logger.debug("[Op] SP response: %s", response) + response = self.send(sp_url, op, **opargs) + logger.debug("[Op] SP response: %s" % response) + print(response.text) if response.status_code != 200: raise SAMLError( - "Request to SP failed: %s" % response.error) + "Request to SP failed: %s" % response.text) # The response might be a AuthnRequest instance in a SOAP envelope # body. If so it's the start of the ECP conversation @@ -282,7 +278,6 @@ class Client(Entity): # header blocks may also be present try: respdict = self.parse_soap_message(response.text) - self.ecp_conversation(respdict, idp_entity_id) # should by now be authenticated so this should go smoothly @@ -290,11 +285,9 @@ class Client(Entity): except (soap.XmlParseError, AssertionError, KeyError): pass - #print("RESP",response, self.http.response) - - if response.status_code != 404: + if response.status_code >= 400: raise SAMLError("Error performing operation: %s" % ( - response.error,)) + response.text,)) return response diff --git a/src/saml2/entity.py b/src/saml2/entity.py index b24c621..1276b80 100644 --- a/src/saml2/entity.py +++ b/src/saml2/entity.py @@ -8,7 +8,7 @@ from binascii import hexlify from hashlib import sha1 from saml2.metadata import ENDPOINTS -from saml2.profile import paos, ecp +from saml2.profile import paos, ecp, samlec from saml2.soap import parse_soap_enveloped_saml_artifact_resolve from saml2.soap import class_instances_from_soap_enveloped_saml_thingies from saml2.soap import open_soap_envelope @@ -407,7 +407,8 @@ class Entity(HTTPBase): """ return class_instances_from_soap_enveloped_saml_thingies(text, [paos, ecp, - samlp]) + samlp, + samlec]) @staticmethod def unpack_soap_message(text): diff --git a/src/saml2/profile/samlec.py b/src/saml2/profile/samlec.py new file mode 100644 index 0000000..b90f6d3 --- /dev/null +++ b/src/saml2/profile/samlec.py @@ -0,0 +1,14 @@ +from saml2 import SamlBase + + +NAMESPACE = 'urn:ietf:params:xml:ns:samlec' + + +class GeneratedKey(SamlBase): + c_tag = 'GeneratedKey' + c_namespace = NAMESPACE + + +ELEMENT_BY_TAG = { + 'GeneratedKey': GeneratedKey, +}