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
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)
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'] }
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
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