Request preparation refactoring
This commit is contained in:
parent
a26772f637
commit
4dcd3cf270
@ -470,6 +470,8 @@ class SamlBase(ExtensionContainer):
|
||||
#c_attribute_required = {}
|
||||
c_child_order = []
|
||||
c_cardinality = {}
|
||||
c_any = None
|
||||
c_any_attribute = None
|
||||
|
||||
def _get_all_c_children_with_order(self):
|
||||
if len(self.c_child_order) > 0:
|
||||
@ -534,7 +536,8 @@ class SamlBase(ExtensionContainer):
|
||||
member = getattr(self, member_name)
|
||||
if member is not None:
|
||||
tree.attrib[xml_attribute] = member
|
||||
# Lastly, call the ExtensionContainers's _add_members_to_element_tree
|
||||
|
||||
# Lastly, call the ExtensionContainers's _add_members_to_element_tree
|
||||
# to convert any extension attributes.
|
||||
ExtensionContainer._add_members_to_element_tree(self, tree)
|
||||
|
||||
|
@ -50,11 +50,34 @@ logger = logging.getLogger(__name__)
|
||||
class Saml2Client(Base):
|
||||
""" The basic pySAML2 service provider class """
|
||||
|
||||
def do_authenticate(self, entityid=None, relay_state="",
|
||||
binding=saml2.BINDING_HTTP_REDIRECT, vorg="",
|
||||
nameid_format=NAMEID_FORMAT_PERSISTENT,
|
||||
scoping=None, consent=None, extensions=None, sign=None):
|
||||
""" Makes an authentication request.
|
||||
def _request_info(self, binding, req_str, destination, relay_state):
|
||||
|
||||
if binding == saml2.BINDING_HTTP_POST:
|
||||
logger.info("HTTP POST")
|
||||
info = self.use_http_form_post(req_str, destination,
|
||||
relay_state)
|
||||
info["url"] = destination
|
||||
info["method"] = "GET"
|
||||
elif binding == saml2.BINDING_HTTP_REDIRECT:
|
||||
logger.info("HTTP REDIRECT")
|
||||
info = self.use_http_get(req_str, destination,
|
||||
relay_state)
|
||||
info["url"] = destination
|
||||
info["method"] = "GET"
|
||||
elif binding == BINDING_SOAP:
|
||||
info = self.use_soap(req_str, destination)
|
||||
else:
|
||||
raise Exception("Unknown binding type: %s" % binding)
|
||||
|
||||
return info
|
||||
|
||||
|
||||
def prepare_for_authenticate(self, entityid=None, relay_state="",
|
||||
binding=saml2.BINDING_HTTP_REDIRECT, vorg="",
|
||||
nameid_format=NAMEID_FORMAT_PERSISTENT,
|
||||
scoping=None, consent=None, extensions=None,
|
||||
sign=None):
|
||||
""" Makes all necessary preparations for an authentication request.
|
||||
|
||||
:param entityid: The entity ID of the IdP to send the request to
|
||||
:param relay_state: To where the user should be returned after
|
||||
@ -65,30 +88,21 @@ class Saml2Client(Base):
|
||||
:param consent: Whether the principal have given her consent
|
||||
:param extensions: Possible extensions
|
||||
:param sign: Whether the request should be signed or not.
|
||||
:return: AuthnRequest response
|
||||
:return: session id and AuthnRequest info
|
||||
"""
|
||||
|
||||
location = self._sso_location(entityid, binding)
|
||||
destination = self._sso_location(entityid, binding)
|
||||
|
||||
req = self.create_authn_request(location, vorg, scoping, binding,
|
||||
req = self.create_authn_request(destination, vorg, scoping, binding,
|
||||
nameid_format, consent, extensions,
|
||||
sign)
|
||||
_req_str = "%s" % req
|
||||
|
||||
logger.info("AuthNReq: %s" % _req_str)
|
||||
|
||||
if binding == saml2.BINDING_HTTP_POST:
|
||||
logger.info("HTTP POST")
|
||||
(header, body) = self.use_http_form_post(_req_str, location,
|
||||
relay_state)
|
||||
elif binding == saml2.BINDING_HTTP_REDIRECT:
|
||||
logger.info("HTTP REDIRECT")
|
||||
(header, body) = self.use_http_get(_req_str, location,
|
||||
relay_state)
|
||||
else:
|
||||
raise Exception("Unknown binding type: %s" % binding)
|
||||
info = self._request_info(binding, _req_str, destination, relay_state)
|
||||
|
||||
return req.id, header, body
|
||||
return req.id, info
|
||||
|
||||
def global_logout(self, subject_id, reason="", expire=None, sign=None):
|
||||
""" More or less a layer of indirection :-/
|
||||
@ -169,12 +183,15 @@ class Saml2Client(Base):
|
||||
logger.info("REQUEST: %s" % request)
|
||||
|
||||
srequest = signed_instance_factory(request, self.sec, to_sign)
|
||||
|
||||
relay_state = self._relay_state(request.id)
|
||||
|
||||
http_info = self._request_info(binding, srequest,
|
||||
destination, relay_state)
|
||||
|
||||
if binding == BINDING_SOAP:
|
||||
response = self.send_using_soap(srequest, destination)
|
||||
if response:
|
||||
logger.info("Verifying response")
|
||||
response = self.logout_request_response(response)
|
||||
response = self.send(**http_info)
|
||||
|
||||
if response:
|
||||
not_done.remove(entity_id)
|
||||
@ -184,27 +201,15 @@ class Saml2Client(Base):
|
||||
logger.info("NOT OK response from %s" % destination)
|
||||
|
||||
else:
|
||||
session_id = request.id
|
||||
rstate = self._relay_state(session_id)
|
||||
self.state[request.id] = {"entity_id": entity_id,
|
||||
"operation": "SLO",
|
||||
"entity_ids": entity_ids,
|
||||
"subject_id": subject_id,
|
||||
"reason": reason,
|
||||
"not_on_of_after": expire,
|
||||
"sign": sign}
|
||||
|
||||
self.state[session_id] = {"entity_id": entity_id,
|
||||
"operation": "SLO",
|
||||
"entity_ids": entity_ids,
|
||||
"subject_id": subject_id,
|
||||
"reason": reason,
|
||||
"not_on_of_after": expire,
|
||||
"sign": sign}
|
||||
|
||||
|
||||
if binding == BINDING_HTTP_POST:
|
||||
response = self.use_http_form_post(srequest,
|
||||
destination,
|
||||
rstate)
|
||||
else:
|
||||
response = self.use_http_get(srequest, destination,
|
||||
rstate)
|
||||
|
||||
responses[entity_id] = response
|
||||
responses[entity_id] = http_info
|
||||
not_done.remove(entity_id)
|
||||
|
||||
# only try one binding
|
||||
@ -247,11 +252,13 @@ class Saml2Client(Base):
|
||||
status["reason"], status["not_on_or_after"],
|
||||
status["sign"])
|
||||
|
||||
# ========================================================================
|
||||
# MUST use SOAP for
|
||||
# AssertionIDRequest, SubjectQuery,
|
||||
# AuthnQuery, AttributeQuery, or AuthzDecisionQuery
|
||||
# AssertionIDRequest, SubjectQuery, AuthnQuery, AttributeQuery or
|
||||
# AuthzDecisionQuery
|
||||
# ========================================================================
|
||||
|
||||
def use_soap(self, destination, query_type, **kwargs):
|
||||
def _use_soap(self, destination, query_type, **kwargs):
|
||||
_create_func = getattr(self, "create_%s" % query_type)
|
||||
_response_func = getattr(self, "%s_response" % query_type)
|
||||
try:
|
||||
@ -296,7 +303,7 @@ class Saml2Client(Base):
|
||||
|
||||
srvs = self.metadata.authz_service(entity_id, BINDING_SOAP)
|
||||
for dest in destinations(srvs):
|
||||
resp = self.use_soap(dest, "authz_decision_query",
|
||||
resp = self._use_soap(dest, "authz_decision_query",
|
||||
action=action, evidence=evidence,
|
||||
resource=resource, subject=subject)
|
||||
if resp:
|
||||
@ -319,7 +326,7 @@ class Saml2Client(Base):
|
||||
_id_refs = [AssertionIDRef(_id) for _id in assertion_ids]
|
||||
|
||||
for destination in destinations(srvs):
|
||||
res = self.use_soap(destination, "assertion_id_request",
|
||||
res = self._use_soap(destination, "assertion_id_request",
|
||||
assertion_id_refs=_id_refs, consent=consent,
|
||||
extensions=extensions, sign=sign)
|
||||
if res:
|
||||
@ -333,7 +340,7 @@ class Saml2Client(Base):
|
||||
srvs = self.metadata.authn_request_service(entity_id, BINDING_SOAP)
|
||||
|
||||
for destination in destinations(srvs):
|
||||
resp = self.use_soap(destination, "authn_query",
|
||||
resp = self._use_soap(destination, "authn_query",
|
||||
consent=consent, extensions=extensions,
|
||||
sign=sign)
|
||||
if resp:
|
||||
@ -376,20 +383,22 @@ class Saml2Client(Base):
|
||||
response_args = {}
|
||||
|
||||
if binding == BINDING_SOAP:
|
||||
return self.use_soap(destination, "attribute_query", consent=consent,
|
||||
extensions=extensions, sign=sign,
|
||||
subject_id=subject_id, attribute=attribute,
|
||||
sp_name_qualifier=sp_name_qualifier,
|
||||
name_qualifier=name_qualifier,
|
||||
nameid_format=nameid_format,
|
||||
response_args=response_args)
|
||||
return self._use_soap(destination, "attribute_query",
|
||||
consent=consent, extensions=extensions,
|
||||
sign=sign, subject_id=subject_id,
|
||||
attribute=attribute,
|
||||
sp_name_qualifier=sp_name_qualifier,
|
||||
name_qualifier=name_qualifier,
|
||||
nameid_format=nameid_format,
|
||||
response_args=response_args)
|
||||
elif binding == BINDING_HTTP_POST:
|
||||
return self.use_soap(destination, "attribute_query", consent=consent,
|
||||
extensions=extensions, sign=sign,
|
||||
subject_id=subject_id, attribute=attribute,
|
||||
sp_name_qualifier=sp_name_qualifier,
|
||||
name_qualifier=name_qualifier,
|
||||
nameid_format=nameid_format,
|
||||
response_args=response_args)
|
||||
return self._use_soap(destination, "attribute_query",
|
||||
consent=consent, extensions=extensions,
|
||||
sign=sign, subject_id=subject_id,
|
||||
attribute=attribute,
|
||||
sp_name_qualifier=sp_name_qualifier,
|
||||
name_qualifier=name_qualifier,
|
||||
nameid_format=nameid_format,
|
||||
response_args=response_args)
|
||||
else:
|
||||
raise Exception("Unsupported binding")
|
@ -22,7 +22,7 @@ to conclude its tasks.
|
||||
from saml2.httpbase import HTTPBase
|
||||
from saml2.mdstore import destinations
|
||||
from saml2.saml import AssertionIDRef, NAMEID_FORMAT_TRANSIENT
|
||||
from saml2.samlp import AuthnQuery
|
||||
from saml2.samlp import AuthnQuery, ArtifactResponse, StatusCode, Status
|
||||
from saml2.samlp import ArtifactResolve
|
||||
from saml2.samlp import artifact_resolve_from_string
|
||||
from saml2.samlp import LogoutRequest
|
||||
@ -64,7 +64,7 @@ from saml2.response import AuthnResponse
|
||||
from saml2 import BINDING_HTTP_REDIRECT
|
||||
from saml2 import BINDING_SOAP
|
||||
from saml2 import BINDING_HTTP_POST
|
||||
from saml2 import BINDING_PAOS
|
||||
from saml2 import BINDING_PAOS, element_to_extension_element
|
||||
import logging
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@ -157,6 +157,8 @@ class Base(HTTPBase):
|
||||
self.logout_requests_signed_default = True
|
||||
self.allow_unsolicited = self.config.getattr("allow_unsolicited", "sp")
|
||||
|
||||
self.artifact2response = {}
|
||||
|
||||
#
|
||||
# Private methods
|
||||
#
|
||||
@ -604,8 +606,29 @@ class Base(HTTPBase):
|
||||
return self._message(ArtifactResolve, destination, id, consent,
|
||||
extensions, sign, artifact=artifact, issuer=issuer)
|
||||
|
||||
def create_artifact_response(self):
|
||||
pass
|
||||
def create_artifact_response(self, artifact, status_code, in_response_to,
|
||||
id=0, consent=None, extensions=None,
|
||||
sign=False):
|
||||
"""
|
||||
|
||||
:param artifact:
|
||||
:param status_code:
|
||||
:param in_response_to:
|
||||
:param id:
|
||||
:param consent:
|
||||
:param extensions:
|
||||
:param sign:
|
||||
:return:
|
||||
"""
|
||||
|
||||
ee = element_to_extension_element(self.artifact2response[artifact])
|
||||
|
||||
status = Status(status_code=StatusCode(value=status_code))
|
||||
|
||||
return self._message(ArtifactResponse, "", id, consent,
|
||||
extensions, sign, in_response_to=in_response_to,
|
||||
status=status,
|
||||
extension_elements=[ee])
|
||||
|
||||
# ======== response handling ===========
|
||||
|
||||
|
@ -159,7 +159,6 @@ class HTTPBase(object):
|
||||
|
||||
return http_form_post_message(message, destination, relay_state)
|
||||
|
||||
|
||||
def use_http_get(self, message, destination, relay_state):
|
||||
"""
|
||||
Send a message using GET, this is the HTTP-Redirect case so
|
||||
@ -175,9 +174,9 @@ class HTTPBase(object):
|
||||
|
||||
return http_redirect_message(message, destination, relay_state)
|
||||
|
||||
def send_using_soap(self, request, destination, headers=None, sign=False):
|
||||
def use_soap(self, request, destination, headers=None, sign=False):
|
||||
"""
|
||||
Send a message using SOAP+POST
|
||||
Construct the necessary information for using SOAP+POST
|
||||
|
||||
:param request:
|
||||
:param destination:
|
||||
@ -198,10 +197,24 @@ class HTTPBase(object):
|
||||
nodeid=request.id)
|
||||
soap_message = _signed
|
||||
|
||||
return {"url": destination, "method": "POST",
|
||||
"data":soap_message, "headers":headers}
|
||||
|
||||
def send_using_soap(self, request, destination, headers=None, sign=False):
|
||||
"""
|
||||
Send a message using SOAP+POST
|
||||
|
||||
:param request:
|
||||
:param destination:
|
||||
:param headers:
|
||||
:param sign:
|
||||
:return:
|
||||
"""
|
||||
|
||||
#_response = self.server.post(soap_message, headers, path=path)
|
||||
try:
|
||||
response = self.send(destination, "POST", data=soap_message,
|
||||
headers=headers)
|
||||
response = self.send(self.use_soap(request, destination, headers,
|
||||
sign))
|
||||
except Exception, exc:
|
||||
logger.info("HTTPClient exception: %s" % (exc,))
|
||||
return None
|
||||
|
@ -67,7 +67,7 @@ def http_form_post_message(message, location, relay_state="", typ="SAMLRequest")
|
||||
if not isinstance(message, basestring):
|
||||
message = "%s" % (message,)
|
||||
|
||||
if typ == "SAMLRequest":
|
||||
if typ == "SAMLRequest" or typ == "SAMLResponse":
|
||||
_msg = base64.b64encode(message)
|
||||
else:
|
||||
_msg = message
|
||||
@ -79,19 +79,19 @@ def http_form_post_message(message, location, relay_state="", typ="SAMLRequest")
|
||||
response.append("""</script>""")
|
||||
response.append("</body>")
|
||||
|
||||
return [("Content-type", "text/html")], response
|
||||
return {"headers": [("Content-type", "text/html")], "data": response}
|
||||
|
||||
#noinspection PyUnresolvedReferences
|
||||
def http_post_message(message, location, relay_state="", typ="SAMLRequest"):
|
||||
"""
|
||||
|
||||
:param message:
|
||||
:param location:
|
||||
:param relay_state:
|
||||
:param typ:
|
||||
:return:
|
||||
"""
|
||||
return [("Content-type", "text/xml")], message
|
||||
##noinspection PyUnresolvedReferences
|
||||
#def http_post_message(message, location, relay_state="", typ="SAMLRequest"):
|
||||
# """
|
||||
#
|
||||
# :param message:
|
||||
# :param location:
|
||||
# :param relay_state:
|
||||
# :param typ:
|
||||
# :return:
|
||||
# """
|
||||
# return {"headers": [("Content-type", "text/xml")], "data": message}
|
||||
|
||||
def http_redirect_message(message, location, relay_state="", typ="SAMLRequest"):
|
||||
"""The HTTP Redirect binding defines a mechanism by which SAML protocol
|
||||
@ -120,7 +120,7 @@ def http_redirect_message(message, location, relay_state="", typ="SAMLRequest"):
|
||||
headers = [('Location', login_url)]
|
||||
body = [""]
|
||||
|
||||
return headers, body
|
||||
return {"headers":headers, "data":body}
|
||||
|
||||
DUMMY_NAMESPACE = "http://example.org/"
|
||||
PREFIX = '<?xml version="1.0" encoding="UTF-8"?>'
|
||||
@ -164,12 +164,12 @@ def make_soap_enveloped_saml_thingy(thingy, header_parts=None):
|
||||
return ElementTree.tostring(envelope, encoding="UTF-8")
|
||||
|
||||
def http_soap_message(message):
|
||||
return ([("Content-type", "application/soap+xml")],
|
||||
make_soap_enveloped_saml_thingy(message))
|
||||
return {"headers": [("Content-type", "application/soap+xml")],
|
||||
"data": make_soap_enveloped_saml_thingy(message)}
|
||||
|
||||
def http_paos(message, extra=None):
|
||||
return ([("Content-type", "application/soap+xml")],
|
||||
make_soap_enveloped_saml_thingy(message, extra))
|
||||
return {"headers":[("Content-type", "application/soap+xml")],
|
||||
"data": make_soap_enveloped_saml_thingy(message, extra)}
|
||||
|
||||
def parse_soap_enveloped_saml(text, body_class, header_class=None):
|
||||
"""Parses a SOAP enveloped SAML thing and returns header parts and body
|
||||
@ -219,3 +219,6 @@ def packager( identifier ):
|
||||
return PACKING[identifier]
|
||||
except KeyError:
|
||||
raise Exception("Unkown binding type: %s" % identifier)
|
||||
|
||||
def factory(binding, message, location, relay_state="", typ="SAMLRequest"):
|
||||
return PACKING[binding](message, location, relay_state, typ)
|
@ -1,7 +1,8 @@
|
||||
import base64
|
||||
import logging
|
||||
|
||||
from attribute_converter import to_local
|
||||
from saml2 import time_util
|
||||
from saml2 import time_util, BINDING_HTTP_REDIRECT, BINDING_HTTP_POST
|
||||
from saml2 import s_utils
|
||||
from saml2.s_utils import OtherError
|
||||
|
||||
@ -32,10 +33,12 @@ class Request(object):
|
||||
self.message = None
|
||||
self.not_on_or_after = 0
|
||||
|
||||
def _loads(self, xmldata, decode=True):
|
||||
if decode:
|
||||
def _loads(self, xmldata, binding):
|
||||
if binding == BINDING_HTTP_REDIRECT:
|
||||
logger.debug("Expected to decode and inflate xml data")
|
||||
decoded_xml = s_utils.decode_base64_and_inflate(xmldata)
|
||||
elif binding == BINDING_HTTP_POST:
|
||||
decoded_xml = base64.b64decode(xmldata)
|
||||
else:
|
||||
decoded_xml = xmldata
|
||||
|
||||
@ -86,8 +89,8 @@ class Request(object):
|
||||
assert self.issue_instant_ok()
|
||||
return self
|
||||
|
||||
def loads(self, xmldata, decode=True):
|
||||
return self._loads(xmldata, decode)
|
||||
def loads(self, xmldata, binding):
|
||||
return self._loads(xmldata, binding)
|
||||
|
||||
def verify(self):
|
||||
try:
|
||||
|
@ -324,6 +324,9 @@ class SubjectConfirmationDataType_(SamlBase):
|
||||
c_attributes['Recipient'] = ('recipient', 'anyURI', False)
|
||||
c_attributes['InResponseTo'] = ('in_response_to', 'NCName', False)
|
||||
c_attributes['Address'] = ('address', 'string', False)
|
||||
c_any = {"namespace":"##any", "processContents":"lax", "minOccurs":"0",
|
||||
"maxOccurs":"unbounded"}
|
||||
c_any_attribute = {"namespace":"##other", "processContents":"lax"}
|
||||
|
||||
def __init__(self,
|
||||
not_before=None,
|
||||
@ -874,6 +877,7 @@ class AttributeType_(SamlBase):
|
||||
c_attributes['NameFormat'] = ('name_format', 'anyURI', False)
|
||||
c_attributes['FriendlyName'] = ('friendly_name', 'string', False)
|
||||
c_child_order.extend(['attribute_value'])
|
||||
c_any_attribute = {"namespace":"##other", "processContents":"lax"}
|
||||
|
||||
def __init__(self,
|
||||
attribute_value=None,
|
||||
@ -1481,6 +1485,7 @@ class AdviceType_(SamlBase):
|
||||
c_children['{urn:oasis:names:tc:SAML:2.0:assertion}EncryptedAssertion'] = ('encrypted_assertion', [EncryptedAssertion])
|
||||
c_cardinality['encrypted_assertion'] = {"min":0}
|
||||
c_child_order.extend(['assertion_id_ref', 'assertion_uri_ref', 'assertion', 'encrypted_assertion'])
|
||||
c_any = {"namespace":"##other", "processContents":"lax"}
|
||||
|
||||
def __init__(self,
|
||||
assertion_id_ref=None,
|
||||
|
@ -88,6 +88,8 @@ class StatusDetailType_(SamlBase):
|
||||
c_attributes = SamlBase.c_attributes.copy()
|
||||
c_child_order = SamlBase.c_child_order[:]
|
||||
c_cardinality = SamlBase.c_cardinality.copy()
|
||||
c_any = {"namespace":"##any", "processContents":"lax", "minOccurs":"0",
|
||||
"maxOccurs":"unbounded"}
|
||||
|
||||
def status_detail_type__from_string(xml_string):
|
||||
return saml2.create_class_from_xml_string(StatusDetailType_, xml_string)
|
||||
@ -1433,6 +1435,7 @@ class ArtifactResponseType_(StatusResponseType_):
|
||||
c_attributes = StatusResponseType_.c_attributes.copy()
|
||||
c_child_order = StatusResponseType_.c_child_order[:]
|
||||
c_cardinality = StatusResponseType_.c_cardinality.copy()
|
||||
c_any = {"namespace":"##any", "processContents":"lax", "minOccurs":"0"}
|
||||
|
||||
def artifact_response_type__from_string(xml_string):
|
||||
return saml2.create_class_from_xml_string(ArtifactResponseType_, xml_string)
|
||||
|
@ -23,9 +23,6 @@ import logging
|
||||
import shelve
|
||||
import sys
|
||||
import memcache
|
||||
from saml2.pack import http_soap_message
|
||||
from saml2.pack import http_redirect_message
|
||||
from saml2.pack import http_post_message
|
||||
from saml2.httpbase import HTTPBase
|
||||
from saml2.mdstore import destinations
|
||||
|
||||
@ -338,10 +335,9 @@ class Server(HTTPBase):
|
||||
if binding == BINDING_SOAP or binding == BINDING_PAOS:
|
||||
# not base64 decoding and unzipping
|
||||
authn_request.debug=True
|
||||
_log_info("Don't decode")
|
||||
authn_request = authn_request.loads(enc_request, decode=False)
|
||||
authn_request = authn_request.loads(enc_request, binding)
|
||||
else:
|
||||
authn_request = authn_request.loads(enc_request)
|
||||
authn_request = authn_request.loads(enc_request, binding)
|
||||
|
||||
_log_debug("Loaded authn_request")
|
||||
|
||||
@ -379,6 +375,7 @@ class Server(HTTPBase):
|
||||
raise UnsupportedBinding(sp_entity_id)
|
||||
|
||||
response["sp_entity_id"] = sp_entity_id
|
||||
response["binding"] = _binding
|
||||
|
||||
if authn_request.message.assertion_consumer_service_url:
|
||||
return_destination = \
|
||||
@ -404,11 +401,11 @@ class Server(HTTPBase):
|
||||
"""
|
||||
return self.metadata.attribute_requirement(sp_entity_id, index)
|
||||
|
||||
def parse_attribute_query(self, xml_string, decode=True):
|
||||
def parse_attribute_query(self, xml_string, binding):
|
||||
""" Parse an attribute query
|
||||
|
||||
:param xml_string: The Attribute Query as an XML string
|
||||
:param decode: Whether the xmlstring is base64encoded and zipped
|
||||
:param binding: Which binding that was used for the request
|
||||
:return: 3-Tuple containing:
|
||||
subject - identifier of the subject
|
||||
attribute - which attributes that the requestor wants back
|
||||
@ -417,7 +414,7 @@ class Server(HTTPBase):
|
||||
receiver_addresses = self.conf.endpoint("attribute_service")
|
||||
attribute_query = AttributeQuery( self.sec, receiver_addresses)
|
||||
|
||||
attribute_query = attribute_query.loads(xml_string, decode=decode)
|
||||
attribute_query = attribute_query.loads(xml_string, binding)
|
||||
attribute_query = attribute_query.verify()
|
||||
|
||||
logger.info("KEYS: %s" % attribute_query.message.keys())
|
||||
@ -716,12 +713,12 @@ class Server(HTTPBase):
|
||||
if binding == BINDING_SOAP:
|
||||
lreq = soap.parse_soap_enveloped_saml_logout_request(text)
|
||||
try:
|
||||
req = req.loads(lreq, False) # Got it over SOAP so no base64+zip
|
||||
req = req.loads(lreq, binding)
|
||||
except Exception:
|
||||
return None
|
||||
else:
|
||||
try:
|
||||
req = req.loads(text)
|
||||
req = req.loads(text, binding)
|
||||
except Exception, exc:
|
||||
logger.error("%s" % (exc,))
|
||||
return None
|
||||
@ -782,7 +779,7 @@ class Server(HTTPBase):
|
||||
|
||||
return response
|
||||
|
||||
def parse_authz_decision_query(self, xml_string):
|
||||
def parse_authz_decision_query(self, xml_string, binding):
|
||||
""" Parse an attribute query
|
||||
|
||||
:param xml_string: The Authz decision Query as an XML string
|
||||
@ -794,7 +791,7 @@ class Server(HTTPBase):
|
||||
receiver_addresses = self.conf.endpoint("attribute_service", "idp")
|
||||
attribute_query = AttributeQuery( self.sec, receiver_addresses)
|
||||
|
||||
attribute_query = attribute_query.loads(xml_string)
|
||||
attribute_query = attribute_query.loads(xml_string, binding)
|
||||
attribute_query = attribute_query.verify()
|
||||
|
||||
# Subject name is a BaseID,NameID or EncryptedID instance
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -29,7 +29,8 @@ CONFIG = {
|
||||
"idp": {
|
||||
"endpoints" : {
|
||||
"single_sign_on_service" : [
|
||||
("%s/sso" % BASE, BINDING_HTTP_REDIRECT)],
|
||||
("%s/sso" % BASE, BINDING_HTTP_REDIRECT),
|
||||
("%s/ssop" % BASE, BINDING_HTTP_POST)],
|
||||
"single_logout_service": [
|
||||
("%s/slo" % BASE, BINDING_SOAP),
|
||||
("%s/slop" % BASE, BINDING_HTTP_POST)],
|
||||
|
@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
import base64
|
||||
from saml2.saml import AUTHN_PASSWORD
|
||||
from saml2.samlp import response_from_string
|
||||
|
||||
@ -372,7 +373,7 @@ class TestServer1():
|
||||
issuer_entity_id = "urn:mace:example.com:saml:roland:idp",
|
||||
reason = "I'm tired of this")
|
||||
|
||||
intermed = s_utils.deflate_and_base64_encode("%s" % (logout_request,))
|
||||
intermed = base64.b64encode("%s" % logout_request)
|
||||
|
||||
#saml_soap = make_soap_enveloped_saml_thingy(logout_request)
|
||||
request = self.server.parse_logout_request(intermed, BINDING_HTTP_POST)
|
||||
@ -399,7 +400,7 @@ class TestServer1():
|
||||
issuer_entity_id = "urn:mace:example.com:saml:roland:idp",
|
||||
reason = "I'm tired of this")
|
||||
|
||||
_ = s_utils.deflate_and_base64_encode("%s" % (logout_request,))
|
||||
#_ = s_utils.deflate_and_base64_encode("%s" % (logout_request,))
|
||||
|
||||
saml_soap = make_soap_enveloped_saml_thingy(logout_request)
|
||||
self.server.close_shelve_db()
|
||||
@ -475,8 +476,8 @@ class TestServerLogout():
|
||||
print request
|
||||
binding = BINDING_HTTP_REDIRECT
|
||||
response = server.create_logout_response(request, binding)
|
||||
headers, message = server.use_http_get(response, response.destination,
|
||||
http_args = server.use_http_get(response, response.destination,
|
||||
"/relay_state")
|
||||
assert len(headers) == 1
|
||||
assert headers[0][0] == "Location"
|
||||
assert message == ['']
|
||||
assert len(http_args) == 2
|
||||
assert http_args["headers"][0][0] == "Location"
|
||||
assert http_args["data"] == ['']
|
||||
|
@ -14,7 +14,7 @@ from saml2.server import Server
|
||||
from saml2.time_util import in_a_while
|
||||
|
||||
from py.test import raises
|
||||
from fakeIDP import FakeIDP
|
||||
from fakeIDP import FakeIDP, unpack_form
|
||||
|
||||
def for_me(condition, me ):
|
||||
for restriction in condition.audience_restriction:
|
||||
@ -341,13 +341,13 @@ class TestClientWithDummy():
|
||||
self.client.send = self.server.receive
|
||||
|
||||
def test_do_authn(self):
|
||||
id, header, body = self.client.do_authenticate(IDP,
|
||||
id, http_args = self.client.prepare_for_authenticate(IDP,
|
||||
"http://www.example.com/relay_state")
|
||||
|
||||
assert isinstance(id, basestring)
|
||||
assert len(header) == 1
|
||||
assert header[0][0] == "Location"
|
||||
assert body == [""]
|
||||
assert len(http_args) == 4
|
||||
assert http_args["headers"][0][0] == "Location"
|
||||
assert http_args["data"] == [""]
|
||||
|
||||
def test_do_attribute_query(self):
|
||||
response = self.client.do_attribute_query(IDP,
|
||||
@ -378,17 +378,11 @@ class TestClientWithDummy():
|
||||
assert resp
|
||||
assert len(resp) == 1
|
||||
assert resp.keys() == entity_ids
|
||||
item = resp[entity_ids[0]]
|
||||
assert isinstance(item, tuple)
|
||||
assert item[0] == [('Content-type', 'text/html')]
|
||||
lead = "name=\"SAMLRequest\" value=\""
|
||||
body = item[1][3]
|
||||
i = body.find(lead)
|
||||
i += len(lead)
|
||||
j = i + body[i:].find('"')
|
||||
info = body[i:j]
|
||||
xml_str = base64.b64decode(info)
|
||||
#xml_str = decode_base64_and_inflate(info)
|
||||
http_args = resp[entity_ids[0]]
|
||||
assert isinstance(http_args, dict)
|
||||
assert http_args["headers"] == [('Content-type', 'text/html')]
|
||||
info = unpack_form(http_args["data"][3])
|
||||
xml_str = base64.b64decode(info["SAMLRequest"])
|
||||
req = logout_request_from_string(xml_str)
|
||||
print req
|
||||
assert req.reason == "Tired"
|
||||
|
Loading…
Reference in New Issue
Block a user