Exemple #1
0
class TestSP():
    def setup_class(self):
        self.sp = make_plugin("rem", saml_conf="server_conf")
        self.server = Server(config_file="idp_conf")

    def test_setup(self):
        assert self.sp
        
    def test_identify(self):

        # Create a SAMLResponse
        ava = { "givenName": ["Derek"], "surname": ["Jeter"], 
                "mail": ["*****@*****.**"]}

        resp_str = "\n".join(self.server.authn_response(ava, 
                    "id1", "http://lingon.catalogix.se:8087/", 
                    "urn:mace:example.com:saml:roland:sp",
                    samlp.NameIDPolicy(format=saml.NAMEID_FORMAT_TRANSIENT,
                                        allow_create="true"),
                    "*****@*****.**"))

        resp_str = base64.encodestring(resp_str)
        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']}
def create_authn_response(session_id, identity=dict(), sign=True):
    config = IdPConfig()
    config.load(idp_config)
    idp_server = Server(config=config)
    idp_server.ident = Identifier(auth.AuthDictCache(dict(), '_ident'))
    authn_response = str(idp_server.authn_response(
        identity=identity,
        in_response_to=session_id,
        destination='https://foo.example.com/sp/acs',
        sp_entity_id='https://foo.example.com/sp/metadata',
        name_id_policy=None,
        userid='Irrelevent',
        sign=sign,
        instance=True))
    response = samlp.response_from_string(authn_response)
    return response.assertion[0].subject.name_id.text, authn_response
Exemple #3
0
def create_authn_response(session_id, identity=dict(), sign=True):
    config = IdPConfig()
    config.load(idp_config)
    idp_server = Server(config=config)
    idp_server.ident = Identifier(auth.AuthDictCache(dict(), '_ident'))
    authn_response = str(
        idp_server.authn_response(
            identity=identity,
            in_response_to=session_id,
            destination='https://foo.example.com/sp/acs',
            sp_entity_id='https://foo.example.com/sp/metadata',
            name_id_policy=None,
            userid='Irrelevent',
            sign=sign,
            instance=True))
    response = samlp.response_from_string(authn_response)
    return response.assertion[0].subject.name_id.text, authn_response
def auth_response(identity, in_response_to, sp_conf):
    """Generates a fresh signed authentication response"""
    sp_entity_id = sp_conf.entityid
    idp_entity_id = sp_conf.idps().keys()[0]
    acs = sp_conf.endpoint('assertion_consumer_service')[0]
    issuer = saml.Issuer(text=idp_entity_id, format=saml.NAMEID_FORMAT_ENTITY)
    response = response_factory(issuer=issuer,
                                in_response_to=in_response_to,
                                destination=acs,
                                status=success_status_factory())
    idp_conf = IdPConfig()
    name_form = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
    idp_conf.load({
        'entityid': idp_entity_id,
        'xmlsec_binary': sp_conf.xmlsec_binary,
        'attribute_map_dir': os.path.join(BASEDIR, 'attribute-maps'),
        'service': {
            'idp': {
                'endpoints': tuple(),
                'policy': {
                    'default': {
                        "lifetime": {
                            "minutes": 15
                        },
                        "attribute_restrictions": None,
                        "name_form": name_form,
                    }
                }
            },
        },
        'key_file': os.path.join(BASEDIR, 'idpcert.key'),
        'cert_file': os.path.join(BASEDIR, 'idpcert.pem'),
        'metadata': {
            'local': [os.path.join(BASEDIR, 'sp_metadata.xml')],
        },
    })
    server = Server("", idp_conf)
    server.ident = Identifier(FakeDb())

    userid = 'irrelevant'
    response = server.authn_response(identity, in_response_to, acs,
                                     sp_entity_id, None, userid)
    return '\n'.join(response)
def auth_response(identity, in_response_to, sp_conf):
    """Generates a fresh signed authentication response"""
    sp_entity_id = sp_conf.entityid
    idp_entity_id = sp_conf.idps().keys()[0]
    acs = sp_conf.endpoint('assertion_consumer_service')[0]
    issuer = saml.Issuer(text=idp_entity_id, format=saml.NAMEID_FORMAT_ENTITY)
    response = response_factory(issuer=issuer,
                                in_response_to=in_response_to,
                                destination=acs,
                                status=success_status_factory())
    idp_conf = IdPConfig()
    name_form = "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
    idp_conf.load({
            'entityid': idp_entity_id,
            'xmlsec_binary': sp_conf.xmlsec_binary,
            'attribute_map_dir': os.path.join(BASEDIR, 'attribute-maps'),
            'service': {
                'idp': {
                    'endpoints': tuple(),
                    'policy':  {
                        'default': {
                            "lifetime": {"minutes": 15},
                            "attribute_restrictions": None,
                            "name_form": name_form,
                            }
                        }
                    },
                },
            'key_file': os.path.join(BASEDIR, 'idpcert.key'),
            'cert_file': os.path.join(BASEDIR, 'idpcert.pem'),
            'metadata': {
                'local': [os.path.join(BASEDIR, 'sp_metadata.xml')],
                },
            })
    server = Server("", idp_conf)
    server.ident = Identifier(FakeDb())

    userid = 'irrelevant'
    response = server.authn_response(identity, in_response_to, acs,
                                     sp_entity_id, None, userid)
    return '\n'.join(response)
Exemple #6
0
class TestSP():
    def setup_class(self):
        self.sp = make_plugin("rem", saml_conf="server_conf")
        self.server = Server(config_file="idp_conf")

    def test_setup(self):
        assert self.sp

    def test_identify(self):

        # Create a SAMLResponse
        ava = {
            "givenName": ["Derek"],
            "surname": ["Jeter"],
            "mail": ["*****@*****.**"]
        }

        resp_str = "\n".join(
            self.server.authn_response(
                ava, "id1", "http://lingon.catalogix.se:8087/",
                "urn:mace:example.com:saml:roland:sp",
                samlp.NameIDPolicy(format=saml.NAMEID_FORMAT_TRANSIENT,
                                   allow_create="true"),
                "*****@*****.**"))

        resp_str = base64.encodestring(resp_str)
        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']
        }
Exemple #7
0
class TestClient:
    def setup_class(self):
        self.server = Server("idp_conf")

        conf = config.SPConfig()
        conf.load_file("server_conf")
        self.client = Saml2Client(conf)
    
    def test_create_attribute_query1(self):
        req = self.client.create_attribute_query("id1",
            "E8042FB4-4D5B-48C3-8E14-8EDD852790DD",
            "https://idp.example.com/idp/",
            nameid_format=saml.NAMEID_FORMAT_PERSISTENT)
        reqstr = "%s" % req.to_string()

        assert req.destination == "https://idp.example.com/idp/"
        assert req.id == "id1"
        assert req.version == "2.0"
        subject = req.subject
        name_id = subject.name_id
        assert name_id.format == saml.NAMEID_FORMAT_PERSISTENT
        assert name_id.text == "E8042FB4-4D5B-48C3-8E14-8EDD852790DD"
        issuer = req.issuer
        assert issuer.text == "urn:mace:example.com:saml:roland:sp"

        attrq = samlp.attribute_query_from_string(reqstr)

        print attrq.keyswv()
        assert _leq(attrq.keyswv(), ['destination', 'subject', 'issue_instant',
                                    'version', 'id', 'issuer'])

        assert attrq.destination == req.destination
        assert attrq.id == req.id
        assert attrq.version == req.version
        assert attrq.issuer.text == issuer.text
        assert attrq.issue_instant == req.issue_instant
        assert attrq.subject.name_id.format == name_id.format
        assert attrq.subject.name_id.text == name_id.text

    def test_create_attribute_query2(self):
        req = self.client.create_attribute_query("id1", 
            "E8042FB4-4D5B-48C3-8E14-8EDD852790DD", 
            "https://idp.example.com/idp/",
            attribute={
                ("urn:oid:2.5.4.42",
                "urn:oasis:names:tc:SAML:2.0:attrname-format:uri",
                "givenName"):None,
                ("urn:oid:2.5.4.4",
                "urn:oasis:names:tc:SAML:2.0:attrname-format:uri",
                "surname"):None,
                ("urn:oid:1.2.840.113549.1.9.1",
                "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"):None,
                },
            nameid_format=saml.NAMEID_FORMAT_PERSISTENT)
                
        print req.to_string()
        assert req.destination == "https://idp.example.com/idp/"
        assert req.id == "id1"
        assert req.version == "2.0"
        subject = req.subject
        name_id = subject.name_id
        assert name_id.format == saml.NAMEID_FORMAT_PERSISTENT
        assert name_id.text == "E8042FB4-4D5B-48C3-8E14-8EDD852790DD"
        assert len(req.attribute) == 3
        # one is givenName
        seen = []
        for attribute in req.attribute:
            if attribute.name == "urn:oid:2.5.4.42":
                assert attribute.name_format == saml.NAME_FORMAT_URI
                assert attribute.friendly_name == "givenName"
                seen.append("givenName")
            elif attribute.name == "urn:oid:2.5.4.4":
                assert attribute.name_format == saml.NAME_FORMAT_URI
                assert attribute.friendly_name == "surname"
                seen.append("surname")
            elif attribute.name == "urn:oid:1.2.840.113549.1.9.1":
                assert attribute.name_format == saml.NAME_FORMAT_URI
                if getattr(attribute,"friendly_name"):
                    assert False
                seen.append("email")
        assert set(seen) == set(["givenName", "surname", "email"])
        
    def test_create_attribute_query_3(self):
        req = self.client.create_attribute_query("id1",
                "_e7b68a04488f715cda642fbdd90099f5", 
                "https://aai-demo-idp.switch.ch/idp/shibboleth",
                nameid_format=saml.NAMEID_FORMAT_TRANSIENT )
                
        assert isinstance(req, samlp.AttributeQuery)
        assert req.destination == "https://aai-demo-idp.switch.ch/idp/shibboleth"
        assert req.id == "id1"
        assert req.version == "2.0"
        assert req.issue_instant
        assert req.issuer.text == "urn:mace:example.com:saml:roland:sp"
        nameid = req.subject.name_id
        assert nameid.format == saml.NAMEID_FORMAT_TRANSIENT
        assert nameid.text == "_e7b68a04488f715cda642fbdd90099f5"

    def test_attribute_query(self):
        req = self.client.attribute_query( 
                "_e7b68a04488f715cda642fbdd90099f5", 
                "https://aai-demo-idp.switch.ch/idp/shibboleth", 
                nameid_format=saml.NAMEID_FORMAT_TRANSIENT)

        # since no one is answering on the other end
        assert req is None
                
    # def test_idp_entry(self):
    #     idp_entry = self.client.idp_entry(name="Umeå Universitet",
    #                         location="https://idp.umu.se/")
    #     
    #     assert idp_entry.name == "Umeå Universitet"
    #     assert idp_entry.loc == "https://idp.umu.se/"
    #     
    # def test_scope(self):
    #     entity_id = "urn:mace:example.com:saml:roland:idp"
    #     locs = self.client.metadata.single_sign_on_services(entity_id)
    #     scope = self.client.scoping_from_metadata(entity_id, locs)
    #     
    #     assert scope.idp_list
    #     assert len(scope.idp_list.idp_entry) == 1
    #     idp_entry = scope.idp_list.idp_entry[0]
    #     assert idp_entry.name == 'Exempel AB'
    #     assert idp_entry.loc == ['http://*****:*****@nyy.mlb.com"]}

        resp_str = "\n".join(self.server.authn_response(
                    identity=ava, 
                    in_response_to="id1", 
                    destination="http://lingon.catalogix.se:8087/", 
                    sp_entity_id="urn:mace:example.com:saml:roland:sp",
                    name_id_policy=samlp.NameIDPolicy(
                        format=saml.NAMEID_FORMAT_PERSISTENT),
                    userid="*****@*****.**"))

        resp_str = base64.encodestring(resp_str)
        
        authn_response = self.client.response({"SAMLResponse":resp_str},
                            {"id1":"http://foo.example.com/service"})
                            
        assert authn_response is not None
        assert authn_response.issuer() == IDP
        assert authn_response.response.assertion[0].issuer.text == IDP
        session_info = authn_response.session_info()

        print session_info
        assert session_info["ava"] == {'mail': ['*****@*****.**'], 'givenName': ['Derek'], 'sn': ['Jeter']}
        assert session_info["issuer"] == IDP
        assert session_info["came_from"] == "http://foo.example.com/service"
        response = samlp.response_from_string(authn_response.xmlstr)        
        assert response.destination == "http://lingon.catalogix.se:8087/"

        # One person in the cache
        assert len(self.client.users.subjects()) == 1
        subject_id = self.client.users.subjects()[0]
        print "||||", self.client.users.get_info_from(subject_id, IDP)
        # The information I have about the subject comes from one source
        assert self.client.users.issuers_of_info(subject_id) == [IDP]

        # --- authenticate another person
        
        ava = { "givenName": ["Alfonson"], "surname": ["Soriano"], 
                "mail": ["*****@*****.**"]}

        resp_str = "\n".join(self.server.authn_response(
                    identity=ava, 
                    in_response_to="id2", 
                    destination="http://lingon.catalogix.se:8087/", 
                    sp_entity_id="urn:mace:example.com:saml:roland:sp",
                    name_id_policy=samlp.NameIDPolicy(
                        format=saml.NAMEID_FORMAT_PERSISTENT),
                    userid="*****@*****.**"))

        resp_str = base64.encodestring(resp_str)
        
        self.client.response({"SAMLResponse":resp_str},
                            {"id2":"http://foo.example.com/service"})
        
        # Two persons in the cache
        assert len(self.client.users.subjects()) == 2
        issuers = [self.client.users.issuers_of_info(s) for s in self.client.users.subjects()]
        # The information I have about the subjects comes from the same source
        print issuers
        assert issuers == [[IDP], [IDP]]
        
    def test_init_values(self):
        entityid = self.client._entityid()
        print entityid
        assert entityid == "urn:mace:example.com:saml:roland:sp"
        print self.client.config.idp
        print self.client.config.metadata.idps()
        print self.client.config.idps()
        location = self.client._sso_location()
        print location
        assert location == 'http://*****:*****@example.com"
            }
        }
        self.client.users.add_information_about_person(session_info)
        entity_ids = self.client.users.issuers_of_info("123456")
        assert entity_ids == ["urn:mace:example.com:saml:roland:idp"]
        resp = self.client.global_logout("123456", "Tired", in_a_while(minutes=5))
        print resp
        assert resp
        assert resp[0] # a session_id
        assert resp[1] == '200 OK'
        assert resp[2] == [('Content-type', 'text/html')]
        assert resp[3][0] == '<head>'
        assert resp[3][1] == '<title>SAML 2.0 POST</title>'
        session_info = self.client.state[resp[0]]
        print session_info
        assert session_info["entity_id"] == entity_ids[0]
        assert session_info["subject_id"] == "123456"
        assert session_info["reason"] == "Tired"
        assert session_info["operation"] == "SLO"
        assert session_info["entity_ids"] == entity_ids
        assert session_info["sign"] == False

    def test_logout_2(self):
        """ one IdP/AA with BINDING_SOAP, can't actually send something"""

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

        # information about the user from an IdP
        session_info = {
            "name_id": "123456",
            "issuer": "urn:mace:example.com:saml:roland:idp",
            "not_on_or_after": in_a_while(minutes=15),
            "ava": {
                "givenName": "Anders",
                "surName": "Andersson",
                "mail": "*****@*****.**"
            }
        }
        client.users.add_information_about_person(session_info)
        entity_ids = self.client.users.issuers_of_info("123456")
        assert entity_ids == ["urn:mace:example.com:saml:roland:idp"]
        destinations = client.config.single_logout_services(entity_ids[0],
                                                            BINDING_SOAP)
        print destinations
        assert destinations == ['http://*****:*****@example.com"
            }
        }
        client.users.add_information_about_person(session_info_authn)
        session_info_aa = {
            "name_id": "123456",
            "issuer": "urn:mace:example.com:saml:roland:aa",
            "not_on_or_after": in_a_while(minutes=15),
            "ava": {
                "eduPersonEntitlement": "Foobar",
            }
        }
        client.users.add_information_about_person(session_info_aa)
        entity_ids = client.users.issuers_of_info("123456")
        assert _leq(entity_ids, ["urn:mace:example.com:saml:roland:idp",
                                "urn:mace:example.com:saml:roland:aa"])
        resp = client.global_logout("123456", "Tired", in_a_while(minutes=5))
        print resp
        assert resp
        assert resp[0] # a session_id
        assert resp[1] == '200 OK'
        # HTTP POST
        assert resp[2] == [('Content-type', 'text/html')]
        assert resp[3][0] == '<head>'
        assert resp[3][1] == '<title>SAML 2.0 POST</title>'
        
        state_info = client.state[resp[0]]
        print state_info
        assert state_info["entity_id"] == entity_ids[0]
        assert state_info["subject_id"] == "123456"
        assert state_info["reason"] == "Tired"
        assert state_info["operation"] == "SLO"
        assert state_info["entity_ids"] == entity_ids
        assert state_info["sign"] == False

    def test_authz_decision_query(self):
        conf = config.SPConfig()
        conf.load_file("server3_conf")
        client = Saml2Client(conf)

        AVA = {'mail': u'*****@*****.**',
               'eduPersonTargetedID': '95e9ae91dbe62d35198fbbd5e1fb0976',
               'displayName': u'Roland Hedberg',
               'uid': 'http://roland.hedberg.myopenid.com/'}

        sp_entity_id = "sp_entity_id"
        in_response_to = "1234"
        consumer_url = "http://example.com/consumer"
        name_id = saml.NameID(saml.NAMEID_FORMAT_TRANSIENT, text="name_id")
        policy = Policy()
        ava = Assertion(AVA)
        assertion = ava.construct(sp_entity_id, in_response_to,
                                    consumer_url, name_id,
                                    conf.attribute_converters,
                                    policy, issuer=client.issuer())

        adq = client.authz_decision_query_using_assertion("entity_id",
                                                         assertion,
                                                        "read",
                                                        "http://example.com/text")

        assert adq
        print adq
        assert adq.keyswv() != []
        assert adq.destination == "entity_id"
        assert adq.resource == "http://example.com/text"
        assert adq.action[0].text == "read"

    def test_request_to_discovery_service(self):
        disc_url = "http://example.com/saml2/idp/disc"
        url = self.client.request_to_discovery_service(disc_url)
        print url
        assert url == "http://example.com/saml2/idp/disc?entityID=urn%3Amace%3Aexample.com%3Asaml%3Aroland%3Asp"

        url = self.client.request_to_discovery_service(disc_url,
                            return_url= "http://example.org/saml2/sp/ds")

        print url
        assert url == "http://example.com/saml2/idp/disc?entityID=urn%3Amace%3Aexample.com%3Asaml%3Aroland%3Asp&return=http%3A%2F%2Fexample.org%2Fsaml2%2Fsp%2Fds"

    def test_get_idp_from_discovery_service(self):
        pdir = {"entityID": "http://example.org/saml2/idp/sso"}
        params = urllib.urlencode(pdir)
        redirect_url = "http://example.com/saml2/sp/disc?%s" % params

        entity_id = self.client.get_idp_from_discovery_service(url=redirect_url)
        assert entity_id == "http://example.org/saml2/idp/sso"

        pdir = {"idpID": "http://example.org/saml2/idp/sso"}
        params = urllib.urlencode(pdir)
        redirect_url = "http://example.com/saml2/sp/disc?%s" % params

        entity_id = self.client.get_idp_from_discovery_service(url=redirect_url,
                                                        returnIDParam="idpID")

        assert entity_id == "http://example.org/saml2/idp/sso"

    def test_unsolicited_response(self):
        """

        """
        self.server = Server("idp_conf")

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

        for subject in self.client.users.subjects():
            self.client.users.remove_person(subject)
            
        IDP = "urn:mace:example.com:saml:roland:idp"

        ava = { "givenName": ["Derek"], "surname": ["Jeter"],
                "mail": ["*****@*****.**"]}

        resp_str = "\n".join(self.server.authn_response(
                    identity=ava,
                    in_response_to="id1",
                    destination="http://lingon.catalogix.se:8087/",
                    sp_entity_id="urn:mace:example.com:saml:roland:sp",
                    name_id_policy=samlp.NameIDPolicy(
                        format=saml.NAMEID_FORMAT_PERSISTENT),
                    userid="*****@*****.**"))

        resp_str = base64.encodestring(resp_str)

        self.client.allow_unsolicited = True
        authn_response = self.client.response({"SAMLResponse":resp_str}, ())
                            
        assert authn_response is not None
        assert authn_response.issuer() == IDP
        assert authn_response.response.assertion[0].issuer.text == IDP
        session_info = authn_response.session_info()

        print session_info
        assert session_info["ava"] == {'mail': ['*****@*****.**'], 'givenName': ['Derek'], 'sn': ['Jeter']}
        assert session_info["issuer"] == IDP
        assert session_info["came_from"] == ""
        response = samlp.response_from_string(authn_response.xmlstr)
        assert response.destination == "http://lingon.catalogix.se:8087/"

        # One person in the cache
        assert len(self.client.users.subjects()) ==  1
Exemple #8
0
class TestClient:
    def setup_class(self):
        self.server = Server("idp_conf")

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

    def test_create_attribute_query1(self):
        req = self.client.create_attribute_query(
            "id1",
            "E8042FB4-4D5B-48C3-8E14-8EDD852790DD",
            "https://idp.example.com/idp/",
            nameid_format=saml.NAMEID_FORMAT_PERSISTENT)
        reqstr = "%s" % req.to_string()

        assert req.destination == "https://idp.example.com/idp/"
        assert req.id == "id1"
        assert req.version == "2.0"
        subject = req.subject
        name_id = subject.name_id
        assert name_id.format == saml.NAMEID_FORMAT_PERSISTENT
        assert name_id.text == "E8042FB4-4D5B-48C3-8E14-8EDD852790DD"
        issuer = req.issuer
        assert issuer.text == "urn:mace:example.com:saml:roland:sp"

        attrq = samlp.attribute_query_from_string(reqstr)

        print attrq.keyswv()
        assert _leq(attrq.keyswv(), [
            'destination', 'subject', 'issue_instant', 'version', 'id',
            'issuer'
        ])

        assert attrq.destination == req.destination
        assert attrq.id == req.id
        assert attrq.version == req.version
        assert attrq.issuer.text == issuer.text
        assert attrq.issue_instant == req.issue_instant
        assert attrq.subject.name_id.format == name_id.format
        assert attrq.subject.name_id.text == name_id.text

    def test_create_attribute_query2(self):
        req = self.client.create_attribute_query(
            "id1",
            "E8042FB4-4D5B-48C3-8E14-8EDD852790DD",
            "https://idp.example.com/idp/",
            attribute={
                ("urn:oid:2.5.4.42", "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", "givenName"):
                None,
                ("urn:oid:2.5.4.4", "urn:oasis:names:tc:SAML:2.0:attrname-format:uri", "surname"):
                None,
                ("urn:oid:1.2.840.113549.1.9.1", "urn:oasis:names:tc:SAML:2.0:attrname-format:uri"):
                None,
            },
            nameid_format=saml.NAMEID_FORMAT_PERSISTENT)

        print req.to_string()
        assert req.destination == "https://idp.example.com/idp/"
        assert req.id == "id1"
        assert req.version == "2.0"
        subject = req.subject
        name_id = subject.name_id
        assert name_id.format == saml.NAMEID_FORMAT_PERSISTENT
        assert name_id.text == "E8042FB4-4D5B-48C3-8E14-8EDD852790DD"
        assert len(req.attribute) == 3
        # one is givenName
        seen = []
        for attribute in req.attribute:
            if attribute.name == "urn:oid:2.5.4.42":
                assert attribute.name_format == saml.NAME_FORMAT_URI
                assert attribute.friendly_name == "givenName"
                seen.append("givenName")
            elif attribute.name == "urn:oid:2.5.4.4":
                assert attribute.name_format == saml.NAME_FORMAT_URI
                assert attribute.friendly_name == "surname"
                seen.append("surname")
            elif attribute.name == "urn:oid:1.2.840.113549.1.9.1":
                assert attribute.name_format == saml.NAME_FORMAT_URI
                if getattr(attribute, "friendly_name"):
                    assert False
                seen.append("email")
        assert set(seen) == set(["givenName", "surname", "email"])

    def test_create_attribute_query_3(self):
        req = self.client.create_attribute_query(
            "id1",
            "_e7b68a04488f715cda642fbdd90099f5",
            "https://aai-demo-idp.switch.ch/idp/shibboleth",
            nameid_format=saml.NAMEID_FORMAT_TRANSIENT)

        assert isinstance(req, samlp.AttributeQuery)
        assert req.destination == "https://aai-demo-idp.switch.ch/idp/shibboleth"
        assert req.id == "id1"
        assert req.version == "2.0"
        assert req.issue_instant
        assert req.issuer.text == "urn:mace:example.com:saml:roland:sp"
        nameid = req.subject.name_id
        assert nameid.format == saml.NAMEID_FORMAT_TRANSIENT
        assert nameid.text == "_e7b68a04488f715cda642fbdd90099f5"

    def test_attribute_query(self):
        req = self.client.attribute_query(
            "_e7b68a04488f715cda642fbdd90099f5",
            "https://aai-demo-idp.switch.ch/idp/shibboleth",
            nameid_format=saml.NAMEID_FORMAT_TRANSIENT)

        # since no one is answering on the other end
        assert req is None

    # def test_idp_entry(self):
    #     idp_entry = self.client.idp_entry(name="Umeå Universitet",
    #                         location="https://idp.umu.se/")
    #
    #     assert idp_entry.name == "Umeå Universitet"
    #     assert idp_entry.loc == "https://idp.umu.se/"
    #
    # def test_scope(self):
    #     entity_id = "urn:mace:example.com:saml:roland:idp"
    #     locs = self.client.metadata.single_sign_on_services(entity_id)
    #     scope = self.client.scoping_from_metadata(entity_id, locs)
    #
    #     assert scope.idp_list
    #     assert len(scope.idp_list.idp_entry) == 1
    #     idp_entry = scope.idp_list.idp_entry[0]
    #     assert idp_entry.name == 'Exempel AB'
    #     assert idp_entry.loc == ['http://*****:*****@nyy.mlb.com"]
        }

        resp_str = "\n".join(
            self.server.authn_response(
                identity=ava,
                in_response_to="id1",
                destination="http://lingon.catalogix.se:8087/",
                sp_entity_id="urn:mace:example.com:saml:roland:sp",
                name_id_policy=samlp.NameIDPolicy(
                    format=saml.NAMEID_FORMAT_PERSISTENT),
                userid="*****@*****.**"))

        resp_str = base64.encodestring(resp_str)

        authn_response = self.client.response(
            {"SAMLResponse": resp_str},
            {"id1": "http://foo.example.com/service"})

        assert authn_response is not None
        assert authn_response.issuer() == IDP
        assert authn_response.response.assertion[0].issuer.text == IDP
        session_info = authn_response.session_info()

        print session_info
        assert session_info["ava"] == {
            'mail': ['*****@*****.**'],
            'givenName': ['Derek'],
            'sn': ['Jeter']
        }
        assert session_info["issuer"] == IDP
        assert session_info["came_from"] == "http://foo.example.com/service"
        response = samlp.response_from_string(authn_response.xmlstr)
        assert response.destination == "http://lingon.catalogix.se:8087/"

        # One person in the cache
        assert len(self.client.users.subjects()) == 1
        subject_id = self.client.users.subjects()[0]
        print "||||", self.client.users.get_info_from(subject_id, IDP)
        # The information I have about the subject comes from one source
        assert self.client.users.issuers_of_info(subject_id) == [IDP]

        # --- authenticate another person

        ava = {
            "givenName": ["Alfonson"],
            "surname": ["Soriano"],
            "mail": ["*****@*****.**"]
        }

        resp_str = "\n".join(
            self.server.authn_response(
                identity=ava,
                in_response_to="id2",
                destination="http://lingon.catalogix.se:8087/",
                sp_entity_id="urn:mace:example.com:saml:roland:sp",
                name_id_policy=samlp.NameIDPolicy(
                    format=saml.NAMEID_FORMAT_PERSISTENT),
                userid="*****@*****.**"))

        resp_str = base64.encodestring(resp_str)

        self.client.response({"SAMLResponse": resp_str},
                             {"id2": "http://foo.example.com/service"})

        # Two persons in the cache
        assert len(self.client.users.subjects()) == 2
        issuers = [
            self.client.users.issuers_of_info(s)
            for s in self.client.users.subjects()
        ]
        # The information I have about the subjects comes from the same source
        print issuers
        assert issuers == [[IDP], [IDP]]

    def test_init_values(self):
        entityid = self.client.config.entityid
        print entityid
        assert entityid == "urn:mace:example.com:saml:roland:sp"
        print self.client.config.idp
        print self.client.config.metadata.idps()
        print self.client.config.idps()
        location = self.client._sso_location()
        print location
        assert location == 'http://*****:*****@example.com"
            }
        }
        self.client.users.add_information_about_person(session_info)
        entity_ids = self.client.users.issuers_of_info("123456")
        assert entity_ids == ["urn:mace:example.com:saml:roland:idp"]
        resp = self.client.global_logout("123456", "Tired",
                                         in_a_while(minutes=5))
        print resp
        assert resp
        assert resp[0]  # a session_id
        assert resp[1] == '200 OK'
        assert resp[2] == [('Content-type', 'text/html')]
        assert resp[3][0] == '<head>'
        assert resp[3][1] == '<title>SAML 2.0 POST</title>'
        session_info = self.client.state[resp[0]]
        print session_info
        assert session_info["entity_id"] == entity_ids[0]
        assert session_info["subject_id"] == "123456"
        assert session_info["reason"] == "Tired"
        assert session_info["operation"] == "SLO"
        assert session_info["entity_ids"] == entity_ids
        assert session_info["sign"] == False

    def test_logout_2(self):
        """ one IdP/AA with BINDING_SOAP, can't actually send something"""

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

        # information about the user from an IdP
        session_info = {
            "name_id": "123456",
            "issuer": "urn:mace:example.com:saml:roland:idp",
            "not_on_or_after": in_a_while(minutes=15),
            "ava": {
                "givenName": "Anders",
                "surName": "Andersson",
                "mail": "*****@*****.**"
            }
        }
        client.users.add_information_about_person(session_info)
        entity_ids = self.client.users.issuers_of_info("123456")
        assert entity_ids == ["urn:mace:example.com:saml:roland:idp"]
        destinations = client.config.single_logout_services(
            entity_ids[0], BINDING_SOAP)
        print destinations
        assert destinations == ['http://*****:*****@example.com"
            }
        }
        client.users.add_information_about_person(session_info_authn)
        session_info_aa = {
            "name_id": "123456",
            "issuer": "urn:mace:example.com:saml:roland:aa",
            "not_on_or_after": in_a_while(minutes=15),
            "ava": {
                "eduPersonEntitlement": "Foobar",
            }
        }
        client.users.add_information_about_person(session_info_aa)
        entity_ids = client.users.issuers_of_info("123456")
        assert _leq(entity_ids, [
            "urn:mace:example.com:saml:roland:idp",
            "urn:mace:example.com:saml:roland:aa"
        ])
        resp = client.global_logout("123456", "Tired", in_a_while(minutes=5))
        print resp
        assert resp
        assert resp[0]  # a session_id
        assert resp[1] == '200 OK'
        # HTTP POST
        assert resp[2] == [('Content-type', 'text/html')]
        assert resp[3][0] == '<head>'
        assert resp[3][1] == '<title>SAML 2.0 POST</title>'

        state_info = client.state[resp[0]]
        print state_info
        assert state_info["entity_id"] == entity_ids[0]
        assert state_info["subject_id"] == "123456"
        assert state_info["reason"] == "Tired"
        assert state_info["operation"] == "SLO"
        assert state_info["entity_ids"] == entity_ids
        assert state_info["sign"] == False

    def test_authz_decision_query(self):
        conf = config.SPConfig()
        conf.load_file("server3_conf")
        client = Saml2Client(conf)

        AVA = {
            'mail': u'*****@*****.**',
            'eduPersonTargetedID': '95e9ae91dbe62d35198fbbd5e1fb0976',
            'displayName': u'Roland Hedberg',
            'uid': 'http://roland.hedberg.myopenid.com/'
        }

        sp_entity_id = "sp_entity_id"
        in_response_to = "1234"
        consumer_url = "http://example.com/consumer"
        name_id = saml.NameID(saml.NAMEID_FORMAT_TRANSIENT, text="name_id")
        policy = Policy()
        ava = Assertion(AVA)
        assertion = ava.construct(sp_entity_id,
                                  in_response_to,
                                  consumer_url,
                                  name_id,
                                  conf.attribute_converters,
                                  policy,
                                  issuer=client._issuer())

        adq = client.authz_decision_query_using_assertion(
            "entity_id", assertion, "read", "http://example.com/text")

        assert adq
        print adq
        assert adq.keyswv() != []
        assert adq.destination == "entity_id"
        assert adq.resource == "http://example.com/text"
        assert adq.action[0].text == "read"

    def test_request_to_discovery_service(self):
        disc_url = "http://example.com/saml2/idp/disc"
        url = self.client.discovery_service_request_url(disc_url)
        print url
        assert url == "http://example.com/saml2/idp/disc?entityID=urn%3Amace%3Aexample.com%3Asaml%3Aroland%3Asp"

        url = self.client.discovery_service_request_url(
            disc_url, return_url="http://example.org/saml2/sp/ds")

        print url
        assert url == "http://example.com/saml2/idp/disc?entityID=urn%3Amace%3Aexample.com%3Asaml%3Aroland%3Asp&return=http%3A%2F%2Fexample.org%2Fsaml2%2Fsp%2Fds"

    def test_get_idp_from_discovery_service(self):
        pdir = {"entityID": "http://example.org/saml2/idp/sso"}
        params = urllib.urlencode(pdir)
        redirect_url = "http://example.com/saml2/sp/disc?%s" % params

        entity_id = self.client.discovery_service_response(url=redirect_url)
        assert entity_id == "http://example.org/saml2/idp/sso"

        pdir = {"idpID": "http://example.org/saml2/idp/sso"}
        params = urllib.urlencode(pdir)
        redirect_url = "http://example.com/saml2/sp/disc?%s" % params

        entity_id = self.client.discovery_service_response(
            url=redirect_url, returnIDParam="idpID")

        assert entity_id == "http://example.org/saml2/idp/sso"

    def test_unsolicited_response(self):
        """

        """
        self.server = Server("idp_conf")

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

        for subject in self.client.users.subjects():
            self.client.users.remove_person(subject)

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

        ava = {
            "givenName": ["Derek"],
            "surname": ["Jeter"],
            "mail": ["*****@*****.**"]
        }

        resp_str = "\n".join(
            self.server.authn_response(
                identity=ava,
                in_response_to="id1",
                destination="http://lingon.catalogix.se:8087/",
                sp_entity_id="urn:mace:example.com:saml:roland:sp",
                name_id_policy=samlp.NameIDPolicy(
                    format=saml.NAMEID_FORMAT_PERSISTENT),
                userid="*****@*****.**"))

        resp_str = base64.encodestring(resp_str)

        self.client.allow_unsolicited = True
        authn_response = self.client.response({"SAMLResponse": resp_str}, ())

        assert authn_response is not None
        assert authn_response.issuer() == IDP
        assert authn_response.response.assertion[0].issuer.text == IDP
        session_info = authn_response.session_info()

        print session_info
        assert session_info["ava"] == {
            'mail': ['*****@*****.**'],
            'givenName': ['Derek'],
            'sn': ['Jeter']
        }
        assert session_info["issuer"] == IDP
        assert session_info["came_from"] == ""
        response = samlp.response_from_string(authn_response.xmlstr)
        assert response.destination == "http://lingon.catalogix.se:8087/"

        # One person in the cache
        assert len(self.client.users.subjects()) == 1