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
Beispiel #2
0
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
Beispiel #3
0
def make_plugin(
    remember_name=None,  # plugin for remember
    cache="",  # cache
    # Which virtual organization to support
    virtual_organization="",
    saml_conf="",
    wayf="",
    sid_store="",
    identity_cache="",
    discovery="",
    idp_query_param="",
):
    if saml_conf is "":
        raise ValueError("must include saml_conf in configuration")

    if remember_name is None:
        raise ValueError("must include remember_name in configuration")

    conf = config_factory("sp", saml_conf)

    scl = Saml2Client(
        config=conf,
        identity_cache=identity_cache,
        virtual_organization=virtual_organization,
    )

    plugin = SAML2Plugin(remember_name, conf, scl, wayf, cache, sid_store,
                         discovery, idp_query_param)
    return plugin
Beispiel #4
0
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
Beispiel #5
0
    def setup_class(self):
        conf = config.SPConfig()
        conf.load_file("server_conf")
        self.sp = Saml2Client(conf)

        vo_name = list(conf.vorg.keys())[0]
        self.vo = conf.vorg[vo_name]
        add_derek_info(self.sp)
Beispiel #6
0
def test_construct_deconstruct_request():
    sp = Saml2Client(config_file=dotname("servera_conf"))
    url = sp.create_discovery_service_request(
        "http://example.com/saml/disco",
        "https://example.com/saml/sp.xml",
        isPassive=True,
        returnIDParam="foo",
        return_url="https://example.com/saml/sp/disc")

    print(url)

    ds = DiscoveryServer(config_file=dotname("disco_conf"))
    dsr = ds.parse_discovery_service_request(url)
    # policy is added by the parsing and verifying method
    assert _eq(dsr.keys(), ["return", "entityID", "returnIDParam",
                            "isPassive", "policy"])
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)
Beispiel #8
0
def test_construct_deconstruct_response():
    sp = Saml2Client(config_file=dotname("servera_conf"))
    url = sp.create_discovery_service_request("http://example.com/saml/disco",
                                              "https://example.com/saml/sp.xml",
                                              isPassive=True,
                                              returnIDParam="foo",
                                              return_url="https://example.com/saml/sp/disc")
    ds = DiscoveryServer(config_file=dotname("disco_conf"))
    dsr = ds.parse_discovery_service_request(url)
    args = dict([(key, dsr[key]) for key in ["returnIDParam", "return"]])
    url = ds.create_discovery_service_response(
        entity_id="https://example.com/saml/idp.xml",
        **args)

    idp_id = sp.parse_discovery_service_response(url, returnIDParam="foo")
    assert idp_id == "https://example.com/saml/idp.xml"
Beispiel #9
0
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"
Beispiel #10
0
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
Beispiel #11
0
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)
Beispiel #12
0
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
Beispiel #13
0
def test_nsprefix2():
    conf = config.SPConfig()
    conf.load_file("servera_conf")
    client = Saml2Client(conf)

    selected_idp = "urn:mace:example.com:saml:roland:idp"

    destination = client._sso_location(selected_idp, BINDING_HTTP_POST)

    reqid, req = client.create_authn_request(
        destination,
        nameid_format=NAMEID_FORMAT_TRANSIENT,
        nsprefix={
            "saml2_tophat": saml.NAMESPACE,
            "saml2p": samlp.NAMESPACE
        })

    txt = "%s" % req

    assert "saml2p:AuthnRequest" in txt
    assert "saml2_tophat:Issuer" in txt
Beispiel #14
0
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
Beispiel #15
0
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)
Beispiel #16
0
 def setup_class(self):
     conf = config.SPConfig()
     conf.load_file("server_conf")
     vo_name = list(conf.vorg.keys())[0]
     self.sp = Saml2Client(conf, virtual_organization=vo_name)
     add_derek_info(self.sp)
Beispiel #17
0
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
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
Beispiel #19
0
def test_construct_1():
    sp = Saml2Client(config_file=dotname("servera_conf"))
    url = sp.create_discovery_service_request("http://example.com/saml/disco",
                                              "https://example.com/saml/sp.xml")

    assert url == "http://example.com/saml/disco?entityID=https%3A%2F%2Fexample.com%2Fsaml%2Fsp.xml"
Beispiel #20
0
from saml2_tophat import extension_elements_to_elements
from saml2_tophat import element_to_extension_element
from saml2_tophat import saml
from saml2_tophat.client import Saml2Client
from saml2_tophat.extension import pefim
from saml2_tophat.extension.pefim import SPCertEnc
from saml2_tophat.samlp import Extensions
from saml2_tophat.samlp import authn_request_from_string
from saml2_tophat.sigver import read_cert_from_file
from pathutils import full_path

__author__ = 'roland'

conf = config.SPConfig()
conf.load_file("server_conf")
client = Saml2Client(conf)

# place a certificate in an authn request
cert = read_cert_from_file(full_path("test.pem"), "pem")

spcertenc = SPCertEnc(x509_data=ds.X509Data(
    x509_certificate=ds.X509Certificate(text=cert)))

extensions = Extensions(
    extension_elements=[element_to_extension_element(spcertenc)])

req_id, req = client.create_authn_request(
    "http://www.example.com/sso",
    "urn:mace:example.com:it:tek",
    nameid_format=saml.NAMEID_FORMAT_PERSISTENT,
    message_id="666",
Beispiel #21
0
    if _args.service_conf_module:
        service_conf = importlib.import_module(_args.service_conf_module)
    else:
        import service_conf

    HOST = service_conf.HOST
    PORT = service_conf.PORT
    # ------- HTTPS -------
    # These should point to relevant files
    SERVER_CERT = service_conf.SERVER_CERT
    SERVER_KEY = service_conf.SERVER_KEY
    # This is of course the certificate chain for the CA that signed
    # your cert and all the way up to the top
    CERT_CHAIN = service_conf.CERT_CHAIN

    SP = Saml2Client(config_file="%s" % CNFBASE)

    POLICY = service_conf.POLICY

    add_urls()
    sign_alg = None
    digest_alg = None
    try:
        sign_alg = service_conf.SIGN_ALG
    except:
        pass
    try:
        digest_alg = service_conf.DIGEST_ALG
    except:
        pass
    ds.DefaultSignature(sign_alg, digest_alg)
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