Merge pull request #407 from cemiarni/master

Fix some ECP problems
This commit is contained in:
Roland Hedberg 2017-04-24 16:00:02 +02:00 committed by GitHub
commit 9e0f8afece
4 changed files with 66 additions and 54 deletions

View File

@ -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):
# ----------------------------------------
# <paos:Request>
# ----------------------------------------
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))
# ----------------------------------------
# <ecp: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))
# ----------------------------------------
# <ecp:RelayState>
# ----------------------------------------
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
# ----------------------------------------
# <samlp:AuthnRequest>
# ----------------------------------------
@ -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)]
# ----------------------------------------
# <ecp: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])
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))
# ----------------------------------------
# <ecp:RelayState>
# ----------------------------------------
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)

View File

@ -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

View File

@ -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):

View File

@ -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,
}