class TestSP(): def setup_class(self): self.sp = make_plugin("rem", saml_conf="server_conf") # Explicitly allow unsigned responses for this test self.sp.saml_client.want_response_signed = False self.server = Server(config_file="idp_conf") def teardown_class(self): self.server.close() def test_setup(self): assert self.sp def test_identify(self): # Create a SAMLResponse ava = {"givenName": ["Derek"], "surName": ["Jeter"], "mail": ["*****@*****.**"], "title": ["The man"]} resp_str = "%s" % self.server.create_authn_response( ava, "id1", "http://lingon.catalogix.se:8087/", "urn:mace:example.com:saml:roland:sp", trans_name_policy, "*****@*****.**", authn=AUTHN) resp_str = base64.encodestring(resp_str.encode('utf-8')) self.sp.outstanding_queries = {"id1": "http://www.example.com/service"} session_info = self.sp._eval_authn_response( {}, {"SAMLResponse": [resp_str]}) assert len(session_info) > 1 assert session_info["came_from"] == 'http://www.example.com/service' assert session_info["ava"] == {'givenName': ['Derek'], 'mail': ['*****@*****.**'], 'sn': ['Jeter'], 'title': ['The man']}
def test_relay_state(): # Identity information about a mock user. identity = { "eduPersonEntitlement": "Short stop", "surName": "Jeter", "givenName": "Derek", "mail": "*****@*****.**", "title": "The man" } # Create a service provider using the servera_conf.py configuration. sp = Saml2Client(config_file="servera_conf") # Create an identity providver using the idp_all_conf.py configuration. with closing(Server(config_file="idp_all_conf")) as idp: # Create a response to an authentication request as if # it came from the SP. name_id = idp.ident.transient_nameid(sp.config.entityid, "id12") binding, destination = idp.pick_binding("assertion_consumer_service", bindings=[BINDING_HTTP_POST], entity_id=sp.config.entityid) resp = idp.create_authn_response(identity, "id-123456789", destination, sp.config.entityid, name_id=name_id) # Apply the HTTP_POST binding to the response with a relay state # typical from a Shibboleth SP to create the HTML that carries # the SAML response. relay_state = SHIB_SP_RELAY_STATE html = idp.apply_binding(BINDING_HTTP_POST, "%s" % resp, destination, relay_state)['data'] # Parse the HTML and verify that it contains the correct relay state. parser = RelayStateHTMLParser(relay_state) parser.feed(html) assert parser.expected_relay_state_found # Apply the HTTP_POST binding to the response with relay state None. relay_state = None html = idp.apply_binding(BINDING_HTTP_POST, "%s" % resp, destination, relay_state)['data'] # Parse the HTML and verify that it does not contain a relay state. parser = RelayStateHTMLParser(relay_state) parser.feed(html) assert not parser.input_relay_state_element_found # Apply the HTTP_POST binding to the response with empty # string relay state. relay_state = "" html = idp.apply_binding(BINDING_HTTP_POST, "%s" % resp, destination, relay_state)['data'] # Parse the HTML and verify that it does not contain a relay state. parser = RelayStateHTMLParser(relay_state) parser.feed(html) assert not parser.input_relay_state_element_found
def setup_class(self): with closing(Server(dotname("idp_conf"))) as server: name_id = server.ident.transient_nameid( "urn:mace:example.com:saml:roland:sp", "id12") self._resp_ = server.create_authn_response( IDENTITY, "id12", # in_response_to "http://lingon.catalogix.se:8087/", # consumer_url "urn:mace:example.com:saml:roland:sp", # sp_entity_id name_id=name_id, authn=AUTHN) self._sign_resp_ = server.create_authn_response( IDENTITY, "id12", # in_response_to "http://lingon.catalogix.se:8087/", # consumer_url "urn:mace:example.com:saml:roland:sp", # sp_entity_id name_id=name_id, sign_assertion=True, authn=AUTHN) self._resp_authn = server.create_authn_response( IDENTITY, "id12", # in_response_to "http://lingon.catalogix.se:8087/", # consumer_url "urn:mace:example.com:saml:roland:sp", # sp_entity_id name_id=name_id, authn=AUTHN) self.conf = config_factory("sp", dotname("server_conf")) self.conf.only_use_keys_in_metadata = False self.ar = authn_response(self.conf, "http://lingon.catalogix.se:8087/")
def setup_class(self): with closing(Server("idp_conf")) as server: name_id = server.ident.transient_nameid( "urn:mace:example.com:saml:roland:sp", "id12") self._resp_ = server.create_authn_response( IDENTITY, "id12", # in_response_to "http://lingon.catalogix.se:8087/", # consumer_url "urn:mace:example.com:saml:roland:sp", # sp_entity_id name_id=name_id) self._sign_resp_ = server.create_authn_response( IDENTITY, "id12", # in_response_to "http://lingon.catalogix.se:8087/", # consumer_url "urn:mace:example.com:saml:roland:sp", # sp_entity_id name_id=name_id, sign_assertion=True) self._resp_authn = server.create_authn_response( IDENTITY, "id12", # in_response_to "http://lingon.catalogix.se:8087/", # consumer_url "urn:mace:example.com:saml:roland:sp", # sp_entity_id name_id=name_id, authn=AUTHN) conf = config.SPConfig() conf.load_file("server_conf") self.conf = conf
def test(): with closing(Server(config_file=dotname("idp_all_conf"))) as idp: conf = SPConfig() conf.load_file(dotname("servera_conf")) sp = Saml2Client(conf) srvs = sp.metadata.single_sign_on_service(idp.config.entityid, BINDING_HTTP_REDIRECT) destination = srvs[0]["location"] req_id, req = sp.create_authn_request(destination, id="id1") signer = sp.sec.sec_backend.get_signer(SIG_RSA_SHA1) info = http_redirect_message(req, destination, relay_state="RS", typ="SAMLRequest", sigalg=SIG_RSA_SHA1, signer=signer) verified_ok = False for param, val in info["headers"]: if param == "Location": _dict = parse_qs(val.split("?")[1]) _certs = idp.metadata.certs(sp.config.entityid, "any", "signing") for cert in _certs: if verify_redirect_signature(list_values2simpletons(_dict), sp.sec.sec_backend, cert): verified_ok = True assert verified_ok
def test_create_artifact_resolve(): b64art = create_artifact(SP, "aabbccddeeffgghhiijj", 1) artifact = base64.b64decode(b64art) #assert artifact[:2] == '\x00\x04' #assert int(artifact[2:4]) == 0 # s = sha1(SP.encode('ascii')) assert artifact[4:24] == s.digest() with closing(Server(config_file="idp_all_conf")) as idp: typecode = artifact[:2] assert typecode == ARTIFACT_TYPECODE destination = idp.artifact2destination(b64art, "spsso") msg_id, msg = idp.create_artifact_resolve(b64art, destination, sid()) print(msg) args = idp.use_soap(msg, destination, None, False) sp = Saml2Client(config_file="servera_conf") ar = sp.parse_artifact_resolve(args["data"]) print(ar) assert ar.artifact.text == b64art
def setup_class(self): self.server = Server("idp_conf") sign_alg = Mock() sign_alg.return_value = ds.SIG_RSA_SHA512 digest_alg = Mock() digest_alg.return_value = ds.DIGEST_SHA512 self.restet_default = ds.DefaultSignature ds.DefaultSignature = MagicMock() ds.DefaultSignature().get_sign_alg = sign_alg ds.DefaultSignature().get_digest_alg = digest_alg conf = config.SPConfig() conf.load_file("server_conf") self.client = client.Saml2Client(conf) self.name_id = self.server.ident.transient_nameid( "urn:mace:example.com:saml:roland:sp", "id12") self.ava = {"givenName": ["Derek"], "surName": ["Jeter"], "mail": ["*****@*****.**"], "title": "The man"}
def test_flow(): sp = Saml2Client(config_file="servera_conf") try: with closing(Server(config_file="idp_conf_mdb")) as idp1: with closing(Server(config_file="idp_conf_mdb")) as idp2: # clean out database idp1.ident.mdb.db.drop() # -- dummy request --- req_id, orig_req = sp.create_authn_request( idp1.config.entityid) # == Create an AuthnRequest response rinfo = idp1.response_args(orig_req, [BINDING_HTTP_POST]) #name_id = idp1.ident.transient_nameid("id12", rinfo["sp_entity_id"]) resp = idp1.create_authn_response( { "eduPersonEntitlement": "Short stop", "surName": "Jeter", "givenName": "Derek", "mail": "*****@*****.**", "title": "The man" }, userid="jeter", authn=AUTHN, **rinfo) # What's stored away is the assertion a_info = idp2.session_db.get_assertion(resp.assertion.id) # Make sure what I got back from MongoDB is the same as I put in assert a_info["assertion"] == resp.assertion # By subject nid = resp.assertion.subject.name_id _assertion = idp2.session_db.get_assertions_by_subject(nid) assert len(_assertion) == 1 assert _assertion[0] == resp.assertion nids = idp2.ident.find_nameid("jeter") assert len(nids) == 1 except ConnectionFailure: pass
class TestSP(): def setup_class(self): self.sp = make_plugin("rem", saml_conf="server_conf") # Explicitly allow unsigned responses for this test self.sp.saml_client.want_response_signed = False self.server = Server(config_file="idp_conf") def teardown_class(self): self.server.close() def test_setup(self): assert self.sp def test_identify(self): # Create a SAMLResponse ava = { "givenName": ["Derek"], "surName": ["Jeter"], "mail": ["*****@*****.**"], "title": ["The man"] } resp_str = "%s" % self.server.create_authn_response( ava, "id1", "http://lingon.catalogix.se:8087/", "urn:mace:example.com:saml:roland:sp", trans_name_policy, "*****@*****.**", authn=AUTHN) resp_str = base64.encodestring(resp_str.encode('utf-8')) self.sp.outstanding_queries = {"id1": "http://www.example.com/service"} session_info = self.sp._eval_authn_response( {}, {"SAMLResponse": [resp_str]}) assert len(session_info) > 1 assert session_info["came_from"] == 'http://www.example.com/service' assert session_info["ava"] == { 'givenName': ['Derek'], 'mail': ['*****@*****.**'], 'sn': ['Jeter'], 'title': ['The man'] }
def test_idp_policy_filter(): with closing(Server("idp_conf_ec")) as idp: ava = {"givenName": ["Derek"], "sn": ["Jeter"], "mail": ["*****@*****.**"], "c": ["USA"], "eduPersonTargetedID": "foo!bar!xyz", "norEduPersonNIN": "19800101134"} policy = idp.config.getattr("policy", "idp") ava = policy.filter(ava, "urn:mace:example.com:saml:roland:sp", idp.metadata) print(ava) assert list(ava.keys()) == [ "eduPersonTargetedID"] # because no entity category
def test_basic(): sp = Saml2Client(config_file="servera_conf") with closing(Server(config_file="idp_all_conf")) as idp: srvs = sp.metadata.authn_query_service(idp.config.entityid) destination = srvs[0]["location"] authn_context = requested_authn_context(INTERNETPROTOCOLPASSWORD) subject = Subject(text="abc", name_id=NameID(format=NAMEID_FORMAT_TRANSIENT)) _id, aq = sp.create_authn_query(subject, destination, authn_context) print(aq) assert isinstance(aq, AuthnQuery)
def test_reshuffle_response(): with closing(Server("idp_conf")) as server: name_id = server.ident.transient_nameid( "urn:mace:example.com:saml:roland:sp", "id12") resp_ = server.create_authn_response( IDENTITY, "id12", "http://lingon.catalogix.se:8087/", "urn:mace:example.com:saml:roland:sp", name_id=name_id) resp2 = pre_encrypt_assertion(resp_) print(resp2) assert resp2.encrypted_assertion.extension_elements
def test_request_response(): sp = Saml2Client(config_file="servera_conf") with closing(Server(config_file="idp_all_conf")) as idp: binding, destination = sp.pick_binding("name_id_mapping_service", entity_id=idp.config.entityid) policy = NameIDPolicy(format=NAMEID_FORMAT_TRANSIENT, sp_name_qualifier="urn:mace:swamid:junk", allow_create="true") nameid = NameID(format=NAMEID_FORMAT_TRANSIENT, text="foobar") mid, nmr = sp.create_name_id_mapping_request(policy, nameid, destination) print(nmr) args = sp.use_soap(nmr, destination) # ------- IDP ------------ req = idp.parse_name_id_mapping_request(args["data"], binding) in_response_to = req.message.id name_id = NameID(format=NAMEID_FORMAT_PERSISTENT, text="foobar") idp_response = idp.create_name_id_mapping_response( name_id, in_response_to=in_response_to) print(idp_response) ht_args = sp.use_soap(idp_response) # ------- SP ------------ _resp = sp.parse_name_id_mapping_request_response( ht_args["data"], binding) print(_resp.response) r_name_id = _resp.response.name_id assert r_name_id.format == NAMEID_FORMAT_PERSISTENT assert r_name_id.text == "foobar"
def test_enc2(): crypto = CryptoBackendXmlSec1(xmlsec_path) with closing(Server("idp_conf")) as server: name_id = server.ident.transient_nameid( "urn:mace:example.com:saml:roland:sp", "id12") resp_ = server.create_authn_response( IDENTITY, "id12", "http://lingon.catalogix.se:8087/", "urn:mace:example.com:saml:roland:sp", name_id=name_id) enc_resp = crypto.encrypt_assertion(resp_, full_path("pubkey.pem"), pre_encryption_part()) print(enc_resp) assert enc_resp
def test_base_request(): sp = Saml2Client(config_file="servera_conf") with closing(Server(config_file="idp_all_conf")) as idp: binding, destination = sp.pick_binding("name_id_mapping_service", entity_id=idp.config.entityid) policy = NameIDPolicy(format=NAMEID_FORMAT_TRANSIENT, sp_name_qualifier="urn:mace:swamid:junk", allow_create="true") nameid = NameID(format=NAMEID_FORMAT_TRANSIENT, text="foobar") mid, nmr = sp.create_name_id_mapping_request(policy, nameid, destination) print(nmr) assert isinstance(nmr, NameIDMappingRequest)
def test_flow(): sp = Saml2Client(config_file="servera_conf") with closing(Server(config_file="idp_all_conf")) as idp: binding, destination = sp.pick_binding("manage_name_id_service", entity_id=idp.config.entityid) nameid = NameID(format=NAMEID_FORMAT_TRANSIENT, text="foobar") newid = NewID(text="Barfoo") mid, midq = sp.create_manage_name_id_request(destination, name_id=nameid, new_id=newid) print(midq) rargs = sp.apply_binding(binding, "%s" % midq, destination, "") # --------- @IDP -------------- _req = idp.parse_manage_name_id_request(rargs["data"], binding) print(_req.message) mnir = idp.create_manage_name_id_response(_req.message, [binding]) if binding != BINDING_SOAP: binding, destination = idp.pick_binding( "manage_name_id_service", entity_id=sp.config.entityid) else: destination = "" respargs = idp.apply_binding(binding, "%s" % mnir, destination, "") print(respargs) # ---------- @SP --------------- _response = sp.parse_manage_name_id_request_response( respargs["data"], binding) print(_response.response) assert _response.response.id == mnir.id
def test_enc1(): with closing(Server("idp_conf")) as server: name_id = server.ident.transient_nameid( "urn:mace:example.com:saml:roland:sp", "id12") resp_ = server.create_authn_response( IDENTITY, "id12", "http://lingon.catalogix.se:8087/", "urn:mace:example.com:saml:roland:sp", name_id=name_id) statement = pre_encrypt_assertion(resp_) tmpl = full_path("enc_tmpl.xml") # tmpl_file = open(tmpl, "w") # tmpl_file.write("%s" % pre_encryption_part()) # tmpl_file.close() data = full_path("pre_enc.xml") # data_file = open(data, "w") # data_file.write("%s" % statement) # data_file.close() key_type = "des-192" com_list = [ xmlsec_path, "encrypt", "--pubkey-cert-pem", full_path("pubkey.pem"), "--session-key", key_type, "--xml-data", data, "--node-xpath", ASSERT_XPATH ] crypto = CryptoBackendXmlSec1(xmlsec_path) (_stdout, _stderr, output) = crypto._run_xmlsec(com_list, [tmpl], exception=EncryptError, validate_output=False) print(output) assert _stderr == "" assert _stdout == ""
def test_basic(): sp = Saml2Client(config_file="servera_conf") with closing(Server(config_file="idp_all_conf")) as idp: # -------- @SP ------------ binding, destination = sp.pick_binding("manage_name_id_service", entity_id=idp.config.entityid) nameid = NameID(format=NAMEID_FORMAT_TRANSIENT, text="foobar") newid = NewID(text="Barfoo") mid, mreq = sp.create_manage_name_id_request(destination, name_id=nameid, new_id=newid) print(mreq) rargs = sp.apply_binding(binding, "%s" % mreq, destination, "") # --------- @IDP -------------- _req = idp.parse_manage_name_id_request(rargs["data"], binding) print(_req.message) assert mid == _req.message.id
def setup_class(self): self.sp = make_plugin("rem", saml_conf="server_conf") # Explicitly allow unsigned responses for this test self.sp.saml_client.want_response_signed = False self.server = Server(config_file="idp_conf")
def __init__(self, config_file="", config=None, cache=None): Server.__init__(self, config_file, config, cache)
class TestSignedResponse(): def setup_class(self): self.server = Server("idp_conf") sign_alg = Mock() sign_alg.return_value = ds.SIG_RSA_SHA512 digest_alg = Mock() digest_alg.return_value = ds.DIGEST_SHA512 self.restet_default = ds.DefaultSignature ds.DefaultSignature = MagicMock() ds.DefaultSignature().get_sign_alg = sign_alg ds.DefaultSignature().get_digest_alg = digest_alg conf = config.SPConfig() conf.load_file("server_conf") self.client = client.Saml2Client(conf) self.name_id = self.server.ident.transient_nameid( "urn:mace:example.com:saml:roland:sp", "id12") self.ava = {"givenName": ["Derek"], "surName": ["Jeter"], "mail": ["*****@*****.**"], "title": "The man"} def teardown_class(self): ds.DefaultSignature = self.restet_default self.server.close() def verify_assertion(self, assertion): assert assertion assert assertion[0].attribute_statement ava = ava = get_ava(assertion[0]) assert ava ==\ {'mail': ['*****@*****.**'], 'givenName': ['Derek'], 'surName': ['Jeter'], 'title': ['The man']} def test_signed_response(self): print(ds.DefaultSignature().get_digest_alg()) name_id = self.server.ident.transient_nameid( "urn:mace:example.com:saml:roland:sp", "id12") ava = {"givenName": ["Derek"], "surName": ["Jeter"], "mail": ["*****@*****.**"], "title": "The man"} signed_resp = self.server.create_authn_response( ava, "id12", # in_response_to "http://lingon.catalogix.se:8087/", # consumer_url "urn:mace:example.com:saml:roland:sp", # sp_entity_id name_id=name_id, sign_assertion=True ) print(signed_resp) assert signed_resp sresponse = response_from_string(signed_resp) assert ds.SIG_RSA_SHA512 in str(sresponse), "Not correctly signed!" assert ds.DIGEST_SHA512 in str(sresponse), "Not correctly signed!" def test_signed_response_1(self): signed_resp = self.server.create_authn_response( self.ava, "id12", # in_response_to "http://lingon.catalogix.se:8087/", # consumer_url "urn:mace:example.com:saml:roland:sp", # sp_entity_id name_id=self.name_id, sign_response=True, sign_assertion=True, ) sresponse = response_from_string(signed_resp) assert ds.SIG_RSA_SHA512 in str(sresponse), "Not correctly signed!" assert ds.DIGEST_SHA512 in str(sresponse), "Not correctly signed!" valid = self.server.sec.verify_signature(signed_resp, self.server.config.cert_file, node_name='urn:oasis:names:tc:SAML:2.0:protocol:Response', node_id=sresponse.id, id_attr="") assert valid assert ds.SIG_RSA_SHA512 in str(sresponse.assertion[0]), "Not correctly signed!" assert ds.DIGEST_SHA512 in str(sresponse.assertion[0]), "Not correctly signed!" valid = self.server.sec.verify_signature(signed_resp, self.server.config.cert_file, node_name='urn:oasis:names:tc:SAML:2.0:assertion:Assertion', node_id=sresponse.assertion[0].id, id_attr="") assert valid self.verify_assertion(sresponse.assertion) def test_signed_response_2(self): signed_resp = self.server.create_authn_response( self.ava, "id12", # in_response_to "http://lingon.catalogix.se:8087/", # consumer_url "urn:mace:example.com:saml:roland:sp", # sp_entity_id name_id=self.name_id, sign_response=True, sign_assertion=True, sign_alg=ds.SIG_RSA_SHA256, digest_alg=ds.DIGEST_SHA256 ) sresponse = response_from_string(signed_resp) assert ds.SIG_RSA_SHA256 in str(sresponse), "Not correctly signed!" assert ds.DIGEST_SHA256 in str(sresponse), "Not correctly signed!" valid = self.server.sec.verify_signature(signed_resp, self.server.config.cert_file, node_name='urn:oasis:names:tc:SAML:2.0:protocol:Response', node_id=sresponse.id, id_attr="") assert valid assert ds.SIG_RSA_SHA256 in str(sresponse.assertion[0]), "Not correctly signed!" assert ds.DIGEST_SHA256 in str(sresponse.assertion[0]), "Not correctly signed!" valid = self.server.sec.verify_signature(signed_resp, self.server.config.cert_file, node_name='urn:oasis:names:tc:SAML:2.0:assertion:Assertion', node_id=sresponse.assertion[0].id, id_attr="") assert valid self.verify_assertion(sresponse.assertion)
def test_flow(): sp = Saml2Client(config_file="servera_conf") with closing(Server(config_file="idp_all_conf")) as idp: relay_state = "FOO" # == Create an AuthnRequest response name_id = idp.ident.transient_nameid(sp.config.entityid, "id12") binding, destination = idp.pick_binding("assertion_consumer_service", entity_id=sp.config.entityid) resp = idp.create_authn_response({"eduPersonEntitlement": "Short stop", "surName": "Jeter", "givenName": "Derek", "mail": "*****@*****.**", "title": "The man"}, "id-123456789", destination, sp.config.entityid, name_id=name_id, authn=AUTHN) hinfo = idp.apply_binding(binding, "%s" % resp, destination, relay_state) # ------- @SP ---------- xmlstr = get_msg(hinfo, binding) # Explicitly allow unsigned responses for this test sp.want_response_signed = False aresp = sp.parse_authn_request_response(xmlstr, binding, {resp.in_response_to: "/"}) binding, destination = sp.pick_binding("authn_query_service", entity_id=idp.config.entityid) authn_context = requested_authn_context(INTERNETPROTOCOLPASSWORD) subject = aresp.assertion.subject aq_id, aq = sp.create_authn_query(subject, destination, authn_context) print(aq) assert isinstance(aq, AuthnQuery) binding = BINDING_SOAP hinfo = sp.apply_binding(binding, "%s" % aq, destination, "state2") # -------- @IDP ---------- xmlstr = get_msg(hinfo, binding) pm = idp.parse_authn_query(xmlstr, binding) msg = pm.message assert msg.id == aq.id p_res = idp.create_authn_query_response(msg.subject, msg.session_index, msg.requested_authn_context) print(p_res) hinfo = idp.apply_binding(binding, "%s" % p_res, "", "state2", response=True) # ------- @SP ---------- xmlstr = get_msg(hinfo, binding) final = sp.parse_authn_query_response(xmlstr, binding) print(final) assert final.response.id == p_res.id
def test_basic_flow(): sp = Saml2Client(config_file="servera_conf") with closing(Server(config_file="idp_all_conf")) as idp: # -------- @IDP ------------- relay_state = "FOO" # -- dummy request --- orig_req = AuthnRequest(issuer=sp._issuer(), name_id_policy=NameIDPolicy( allow_create="true", format=NAMEID_FORMAT_TRANSIENT)) # == Create an AuthnRequest response name_id = idp.ident.transient_nameid("id12", sp.config.entityid) binding, destination = idp.pick_binding("assertion_consumer_service", entity_id=sp.config.entityid) resp = idp.create_authn_response( { "eduPersonEntitlement": "Short stop", "surName": "Jeter", "givenName": "Derek", "mail": "*****@*****.**", "title": "The man" }, "id-123456789", destination, sp.config.entityid, name_id=name_id, authn=AUTHN) hinfo = idp.apply_binding(binding, "%s" % resp, destination, relay_state) # --------- @SP ------------- xmlstr = get_msg(hinfo, binding) # Explicitly allow unsigned responses for this test sp.want_response_signed = False aresp = sp.parse_authn_request_response(xmlstr, binding, {resp.in_response_to: "/"}) # == Look for assertion X asid = aresp.assertion.id binding, destination = sp.pick_binding("assertion_id_request_service", entity_id=idp.config.entityid) hinfo = sp.apply_binding(binding, asid, destination) # ---------- @IDP ------------ aid = get_msg(hinfo, binding, response=False) # == construct response resp = idp.create_assertion_id_request_response(aid) hinfo = idp.apply_binding(binding, "%s" % resp, None, "", response=True) # ----------- @SP ------------- xmlstr = get_msg(hinfo, binding, response=True) final = sp.parse_assertion_id_request_response(xmlstr, binding) print(final.response) assert isinstance(final.response, Assertion)
def __init__(self, config_file=""): Server.__init__(self, config_file)
def test_artifact_flow(): #SP = 'urn:mace:example.com:saml:roland:sp' sp = Saml2Client(config_file="servera_conf") with closing(Server(config_file="idp_all_conf")) as idp: # original request binding, destination = sp.pick_binding("single_sign_on_service", entity_id=idp.config.entityid) relay_state = "RS0" req_id, req = sp.create_authn_request(destination, id="id1") artifact = sp.use_artifact(req, 1) binding, destination = sp.pick_binding("single_sign_on_service", [BINDING_HTTP_ARTIFACT], entity_id=idp.config.entityid) hinfo = sp.apply_binding(binding, artifact, destination, relay_state) # ========== @IDP ============ artifact2 = get_msg(hinfo, binding) assert artifact == artifact2 # The IDP now wants to replace the artifact with the real request destination = idp.artifact2destination(artifact2, "spsso") msg_id, msg = idp.create_artifact_resolve(artifact2, destination, sid()) hinfo = idp.use_soap(msg, destination, None, False) # ======== @SP ========== msg = get_msg(hinfo, BINDING_SOAP) ar = sp.parse_artifact_resolve(msg) assert ar.artifact.text == artifact # The SP picks the request out of the repository with the artifact as the key oreq = sp.artifact[ar.artifact.text] # Should be the same as req above # Returns the information over the existing SOAP connection so # no transport information needed msg = sp.create_artifact_response(ar, ar.artifact.text) hinfo = sp.use_soap(msg, destination) # ========== @IDP ============ msg = get_msg(hinfo, BINDING_SOAP) # The IDP untangles the request from the artifact resolve response spreq = idp.parse_artifact_resolve_response(msg) # should be the same as req above assert spreq.id == req.id # That was one way, the Request from the SP # ---------------------------------------------# # Now for the other, the response from the IDP name_id = idp.ident.transient_nameid(sp.config.entityid, "derek") resp_args = idp.response_args(spreq, [BINDING_HTTP_POST]) response = idp.create_authn_response( { "eduPersonEntitlement": "Short stop", "surName": "Jeter", "givenName": "Derek", "mail": "*****@*****.**", "title": "The man" }, name_id=name_id, authn=AUTHN, **resp_args) print(response) # with the response in hand create an artifact artifact = idp.use_artifact(response, 1) binding, destination = sp.pick_binding("single_sign_on_service", [BINDING_HTTP_ARTIFACT], entity_id=idp.config.entityid) hinfo = sp.apply_binding(binding, "%s" % artifact, destination, relay_state, response=True) # ========== SP ========= artifact3 = get_msg(hinfo, binding) assert artifact == artifact3 destination = sp.artifact2destination(artifact3, "idpsso") # Got an artifact want to replace it with the real message msg_id, msg = sp.create_artifact_resolve(artifact3, destination, sid()) print(msg) hinfo = sp.use_soap(msg, destination, None, False) # ======== IDP ========== msg = get_msg(hinfo, BINDING_SOAP) ar = idp.parse_artifact_resolve(msg) print(ar) assert ar.artifact.text == artifact3 # The IDP retrieves the response from the database using the artifact as the key #oreq = idp.artifact[ar.artifact.text] binding, destination = idp.pick_binding("artifact_resolution_service", entity_id=sp.config.entityid) resp = idp.create_artifact_response(ar, ar.artifact.text) hinfo = idp.use_soap(resp, destination) # ========== SP ============ msg = get_msg(hinfo, BINDING_SOAP) sp_resp = sp.parse_artifact_resolve_response(msg) assert sp_resp.id == response.id
def test_complete_flow(): client = ecp_client.Client("user", "password", metadata_file=full_path("idp_all.xml")) sp = Saml2Client(config_file=dotname("servera_conf")) with closing(Server(config_file=dotname("idp_all_conf"))) as idp: IDP_ENTITY_ID = idp.config.entityid #SP_ENTITY_ID = sp.config.entityid # ------------ @Client ----------------------------- headers = client.add_paos_headers([]) assert len(headers) == 2 # ------------ @SP ----------------------------- response = DummyResponse(set_list2dict(headers)) assert sp.can_handle_ecp_response(response) sid, message = sp.create_ecp_authn_request(IDP_ENTITY_ID, relay_state="XYZ") # ------------ @Client ----------------------------- respdict = client.parse_soap_message(message) cargs = client.parse_sp_ecp_response(respdict) assert isinstance(respdict["body"], AuthnRequest) assert len(respdict["header"]) == 2 item0 = respdict["header"][0] assert isinstance(item0, Request) or isinstance(item0, RelayState) destination = respdict["body"].destination ht_args = client.apply_binding(BINDING_SOAP, respdict["body"], destination) # Time to send to the IDP # ----------- @IDP ------------------------------- req = idp.parse_authn_request(ht_args["data"], BINDING_SOAP) assert isinstance(req.message, AuthnRequest) # create Response and return in the SOAP response sp_entity_id = req.sender() name_id = idp.ident.transient_nameid("id12", sp.config.entityid) binding, destination = idp.pick_binding("assertion_consumer_service", [BINDING_PAOS], entity_id=sp_entity_id) resp = idp.create_ecp_authn_request_response(destination, { "eduPersonEntitlement": "Short stop", "surName": "Jeter", "givenName": "Derek", "mail": "*****@*****.**", "title": "The man" }, req.message.id, destination, sp_entity_id, name_id=name_id, authn=AUTHN) # ------------ @Client ----------------------------- # The client got the response from the IDP repackage and send it to the SP respdict = client.parse_soap_message(resp) idp_response = respdict["body"] assert isinstance(idp_response, Response) assert len(respdict["header"]) == 1 _ecp_response = None for item in respdict["header"]: if item.c_tag == "Response" and item.c_namespace == ecp_prof.NAMESPACE: _ecp_response = item #_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"]]) print(ht_args) # ------------ @SP ----------------------------- respdict = sp.unpack_soap_message(ht_args["data"]) # verify the relay_state for header in respdict["header"]: inst = create_class_from_xml_string(RelayState, header) if isinstance(inst, RelayState): assert inst.text == "XYZ" # parse the response # Explicitly allow unsigned responses for this test sp.want_response_signed = False resp = sp.parse_authn_request_response(respdict["body"], None, {sid: "/"}) print(resp.response) assert resp.response.destination == "http://lingon.catalogix.se:8087/paos" assert resp.response.status.status_code.value == STATUS_SUCCESS