コード例 #1
0
    def testAccessors(self):
        """Test for LogoutRequest accessors"""
        self.lr.id = "request id"
        self.lr.version = saml2.VERSION
        self.lr.issue_instant = "2007-09-14T01:05:02Z"
        self.lr.destination = "http://www.example.com/Destination"
        self.lr.consent = saml.CONSENT_UNSPECIFIED
        self.lr.issuer = saml.Issuer()
        self.lr.signature = ds.Signature()
        self.lr.extensions = samlp.Extensions()

        self.lr.not_on_or_after = "2007-10-14T01:05:02Z"
        self.lr.reason = "http://www.example.com/Reason"
        self.lr.base_id = saml.BaseID()
        self.lr.name_id = saml.NameID()
        self.lr.encrypted_id = saml.EncryptedID()
        self.lr.session_index = samlp.SessionIndex()

        new_lr = samlp.logout_request_from_string(self.lr.to_string())
        assert new_lr.id == "request id"
        assert new_lr.version == saml2.VERSION
        assert new_lr.issue_instant == "2007-09-14T01:05:02Z"
        assert new_lr.destination == "http://www.example.com/Destination"
        assert new_lr.consent == saml.CONSENT_UNSPECIFIED
        assert isinstance(new_lr.issuer, saml.Issuer)
        assert isinstance(new_lr.signature, ds.Signature)
        assert isinstance(new_lr.extensions, samlp.Extensions)
        assert new_lr.not_on_or_after == "2007-10-14T01:05:02Z"
        assert new_lr.reason == "http://www.example.com/Reason"
        assert isinstance(new_lr.base_id, saml.BaseID)
        assert isinstance(new_lr.name_id, saml.NameID)
        assert isinstance(new_lr.encrypted_id, saml.EncryptedID)
        assert isinstance(new_lr.session_index[0], samlp.SessionIndex)
コード例 #2
0
ファイル: test_04_samlp.py プロジェクト: lvanderree/pysaml2-3
    def testAccessors(self):
        """Test for LogoutRequest accessors"""
        self.lr.id = "request id"
        self.lr.version = saml2.VERSION
        self.lr.issue_instant = "2007-09-14T01:05:02Z"
        self.lr.destination = "http://www.example.com/Destination"
        self.lr.consent = saml.CONSENT_UNSPECIFIED
        self.lr.issuer = saml.Issuer()
        self.lr.signature = ds.Signature()
        self.lr.extensions = samlp.Extensions()

        self.lr.not_on_or_after = "2007-10-14T01:05:02Z"
        self.lr.reason = "http://www.example.com/Reason"
        self.lr.base_id = saml.BaseID()
        self.lr.name_id = saml.NameID()
        self.lr.encrypted_id = saml.EncryptedID()
        self.lr.session_index = samlp.SessionIndex()

        new_lr = samlp.logout_request_from_string(self.lr.to_string())
        assert new_lr.id == "request id"
        assert new_lr.version == saml2.VERSION
        assert new_lr.issue_instant == "2007-09-14T01:05:02Z"
        assert new_lr.destination == "http://www.example.com/Destination"
        assert new_lr.consent == saml.CONSENT_UNSPECIFIED
        assert isinstance(new_lr.issuer, saml.Issuer)
        assert isinstance(new_lr.signature, ds.Signature)
        assert isinstance(new_lr.extensions, samlp.Extensions)
        assert new_lr.not_on_or_after == "2007-10-14T01:05:02Z"
        assert new_lr.reason == "http://www.example.com/Reason"
        assert isinstance(new_lr.base_id, saml.BaseID)
        assert isinstance(new_lr.name_id, saml.NameID)
        assert isinstance(new_lr.encrypted_id, saml.EncryptedID)
        assert isinstance(new_lr.session_index[0], samlp.SessionIndex)
コード例 #3
0
    def correctly_signed_logout_request(self,
                                        decoded_xml,
                                        must=False,
                                        origdoc=None):
        """ Check if a request is correctly signed, if we have metadata for
        the SP that sent the info use that, if not use the key that are in 
        the message if any.

        :param decoded_xml: The SAML message as a XML string
        :param must: Whether there must be a signature
        :param origdoc: The original XML message
        :return: None if the signature can not be verified otherwise
            request as a samlp.Request instance
        """
        request = samlp.logout_request_from_string(decoded_xml)
        if not request:
            raise TypeError("Not a LogoutRequest")

        if not request.signature:
            if must:
                raise SignatureError("Missing must signature")
            else:
                return request

        return self._check_signature(decoded_xml, request, class_name(request),
                                     origdoc)
コード例 #4
0
ファイル: test_51_client.py プロジェクト: FluidReview/saml2
    def test_logout_1(self):
        """ one IdP/AA logout from"""

        # 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": "*****@*****.**"
            }
        }
        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 len(resp) == 1
        assert resp.keys() == entity_ids
        http_args = resp[entity_ids[0]]
        assert isinstance(http_args, dict)
        assert http_args["headers"] == [('Content-type', 'text/html')]
        info = unpack_form(http_args["data"][3])
        xml_str = base64.b64decode(info["SAMLRequest"])
        req = logout_request_from_string(xml_str)
        print req
        assert req.reason == "Tired"
コード例 #5
0
ファイル: client.py プロジェクト: Wazoku/pysaml2
    def http_redirect_logout_request(self, get, subject_id, log=None):
        """ Deal with a LogoutRequest received through HTTP redirect

        :param get: The request as a dictionary 
        :param subject_id: the id of the current logged user
        :return: a tuple with a list of header tuples (presently only location)
            and a status which will be True in case of success or False 
            otherwise.
        """
        headers = []
        success = False
        if log is None:
            log = self.logger

        try:
            saml_request = get['SAMLRequest']
        except KeyError:
            return None

        if saml_request:
            xml = decode_base64_and_inflate(saml_request)

            request = samlp.logout_request_from_string(xml)
            if log:
                log.debug(request)

            if request.name_id.text == subject_id:
                status = samlp.STATUS_SUCCESS
                success = self.local_logout(subject_id)
            else:
                status = samlp.STATUS_REQUEST_DENIED

            response, destination = self .make_logout_response(
                                                        request.issuer.text,
                                                        request.id,
                                                        status)

            if log:
                log.info("RESPONSE: {0:>s}".format(response))

            if 'RelayState' in get:
                rstate = get['RelayState']
            else:
                rstate = ""
                
            (headers, _body) = http_redirect_message(str(response), 
                                                    destination, 
                                                    rstate, 'SAMLResponse')

        return headers, success
コード例 #6
0
ファイル: test_04_samlp.py プロジェクト: lvanderree/pysaml2-3
 def testUsingTestData(self):
     """Test for logout_request_from_string() using test data"""
     new_lr = samlp.logout_request_from_string(samlp_data.TEST_LOGOUT_REQUEST)
     assert new_lr.id == "request id"
     assert new_lr.version == saml2.VERSION
     assert new_lr.issue_instant == "2007-09-14T01:05:02Z"
     assert new_lr.destination == "http://www.example.com/Destination"
     assert new_lr.consent == saml.CONSENT_UNSPECIFIED
     assert isinstance(new_lr.issuer, saml.Issuer)
     assert isinstance(new_lr.signature, ds.Signature)
     assert isinstance(new_lr.extensions, samlp.Extensions)
     assert new_lr.not_on_or_after == "2007-10-14T01:05:02Z"
     assert new_lr.reason == "http://www.example.com/Reason"
     assert isinstance(new_lr.base_id, saml.BaseID)
     assert isinstance(new_lr.name_id, saml.NameID)
     assert isinstance(new_lr.encrypted_id, saml.EncryptedID)
     assert isinstance(new_lr.session_index[0], samlp.SessionIndex)
     assert new_lr.session_index[0].text.strip() == "session index"
コード例 #7
0
 def testUsingTestData(self):
     """Test for logout_request_from_string() using test data"""
     new_lr = samlp.logout_request_from_string(samlp_data.TEST_LOGOUT_REQUEST)
     assert new_lr.id == "request id"
     assert new_lr.version == saml2.VERSION
     assert new_lr.issue_instant == "2007-09-14T01:05:02Z"
     assert new_lr.destination == "http://www.example.com/Destination"
     assert new_lr.consent == saml.CONSENT_UNSPECIFIED
     assert isinstance(new_lr.issuer, saml.Issuer)
     assert isinstance(new_lr.signature, ds.Signature)
     assert isinstance(new_lr.extensions, samlp.Extensions)
     assert new_lr.not_on_or_after == "2007-10-14T01:05:02Z"
     assert new_lr.reason == "http://www.example.com/Reason"
     assert isinstance(new_lr.base_id, saml.BaseID)
     assert isinstance(new_lr.name_id, saml.NameID)
     assert isinstance(new_lr.encrypted_id, saml.EncryptedID)
     assert isinstance(new_lr.session_index[0], samlp.SessionIndex)
     assert new_lr.session_index[0].text.strip() == "session index"
コード例 #8
0
    def http_redirect_logout_request(self, get, subject_id):
        """ Deal with a LogoutRequest received through HTTP redirect

        :param get: The request as a dictionary 
        :param subject_id: the id of the current logged user
        :return: a tuple with a list of header tuples (presently only location)
            and a status which will be True in case of success or False 
            otherwise.
        """
        headers = []
        success = False

        try:
            saml_request = get['SAMLRequest']
        except KeyError:
            return None

        if saml_request:
            xml = decode_base64_and_inflate(saml_request)

            request = samlp.logout_request_from_string(xml)
            logger.debug(request)

            if request.name_id.text == subject_id:
                status = samlp.STATUS_SUCCESS
                success = self.local_logout(subject_id)
            else:
                status = samlp.STATUS_REQUEST_DENIED

            response, destination = self.make_logout_response(
                request.issuer.text, request.id, status)

            logger.info("RESPONSE: {0:>s}".format(response))

            if 'RelayState' in get:
                rstate = get['RelayState']
            else:
                rstate = ""

            (headers, _body) = http_redirect_message(str(response),
                                                     destination, rstate,
                                                     'SAMLResponse')

        return headers, success
コード例 #9
0
    def http_redirect_logout_request_check_session_index(self, get, session_index, log=None):
        """ Deal with a LogoutRequest received through HTTP redirect

        :param get: The request as a dictionary 
        :param subject_id: the id of the current logged user
        :return: a tuple with a list of header tuples (presently only location)
        """
        msg = {}

        try:
            saml_request = get['SAMLRequest']
        except KeyError:
            return None

        if saml_request:
            xml = decode_base64_and_inflate(saml_request)
            logger.info('logout request: %s' % xml)
            request = samlp.logout_request_from_string(xml)
            logger.debug(request)

            if request.session_index[0].text == session_index:
                status = samlp.STATUS_SUCCESS
            else:
                status = samlp.STATUS_REQUEST_DENIED

            response, destination = self .make_logout_response(
                                                        request.issuer.text,
                                                        request.id,
                                                        status)

            logger.info("RESPONSE: {0:>s}".format(response))

            if 'RelayState' in get:
                rstate = get['RelayState']
            else:
                rstate = ""
            msg = http_redirect_message(str(response),
                                        destination,
                                        rstate, 'SAMLResponse')

        return msg
コード例 #10
0
    def http_redirect_logout_request_check_session_index(
            self, get, session_index, log=None):
        """ Deal with a LogoutRequest received through HTTP redirect

        :param get: The request as a dictionary 
        :param subject_id: the id of the current logged user
        :return: a tuple with a list of header tuples (presently only location)
        """
        msg = {}

        try:
            saml_request = get['SAMLRequest']
        except KeyError:
            return None

        if saml_request:
            xml = decode_base64_and_inflate(saml_request)
            logger.info('logout request: %s' % xml)
            request = samlp.logout_request_from_string(xml)
            logger.debug(request)

            if request.session_index[0].text == session_index:
                status = samlp.STATUS_SUCCESS
            else:
                status = samlp.STATUS_REQUEST_DENIED

            response, destination = self.make_logout_response(
                request.issuer.text, request.id, status)

            logger.info("RESPONSE: {0:>s}".format(response))

            if 'RelayState' in get:
                rstate = get['RelayState']
            else:
                rstate = ""
            msg = http_redirect_message(str(response), destination, rstate,
                                        'SAMLResponse')

        return msg
コード例 #11
0
    def logout_endpoint(self, xml_str, binding):
        if binding == BINDING_SOAP:
            _str = parse_soap_enveloped_saml_logout_request(xml_str)
        else:
            _str = xml_str

        req = logout_request_from_string(_str)

        _resp = self.create_logout_response(req, [binding])

        if binding == BINDING_SOAP:
            # SOAP packing
            #headers = {"content-type": "application/soap+xml"}
            soap_message = make_soap_enveloped_saml_thingy(_resp)
            #            if self.sign and self.sec:
            #                _signed = self.sec.sign_statement_using_xmlsec(soap_message,
            #                                                               class_name(attr_resp),
            #                                                               nodeid=attr_resp.id)
            #                soap_message = _signed
            response = "%s" % soap_message
        else: # Just POST
            response = "%s" % _resp

        return DummyResponse(200, response)
コード例 #12
0
ファイル: sigver.py プロジェクト: FluidReview/saml2
    def correctly_signed_logout_request(self, decoded_xml, must=False,
                                        origdoc=None):
        """ Check if a request is correctly signed, if we have metadata for
        the SP that sent the info use that, if not use the key that are in
        the message if any.

        :param decoded_xml: The SAML message as a XML string
        :param must: Whether there must be a signature
        :param origdoc: The original XML message
        :return: None if the signature can not be verified otherwise
            request as a samlp.Request instance
        """
        request = samlp.logout_request_from_string(decoded_xml)
        if not request:
            raise TypeError("Not a LogoutRequest")

        if not request.signature:
            if must:
                raise SignatureError("Missing must signature")
            else:
                return request

        return self._check_signature(decoded_xml, request,
                                     class_name(request), origdoc)
コード例 #13
0
ファイル: test_51_client.py プロジェクト: GSA/pysaml2
    def test_logout_1(self):
        """ one IdP/AA logout from"""

        # 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": "*****@*****.**"
            }
        }
        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 len(resp) == 1
        assert resp.keys() == entity_ids
        item = resp[entity_ids[0]]
        assert isinstance(item, tuple)
        assert item[0] == [('Content-type', 'text/html')]
        lead = "name=\"SAMLRequest\" value=\""
        body = item[1][3]
        i = body.find(lead)
        i += len(lead)
        j = i + body[i:].find('"')
        info = body[i:j]
        xml_str = base64.b64decode(info)
        #xml_str = decode_base64_and_inflate(info)
        req = logout_request_from_string(xml_str)
        print req
        assert req.reason == "Tired"

#    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"] == True
#
#    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.create_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 = discovery_service_request_url("urn:mace:example.com:saml:roland:sp",
#                                            disc_url)
#        print url
#        assert url == "http://example.com/saml2/idp/disc?entityID=urn%3Amace%3Aexample.com%3Asaml%3Aroland%3Asp"
#
#        url = discovery_service_request_url(
#                            self.client.config.entityid,
#                            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 = 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 = discovery_service_response(url=redirect_url,
#                                               returnIDParam="idpID")
#
#        assert entity_id == "http://example.org/saml2/idp/sso"
#        self.server.close_shelve_db()
#
#    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": ["*****@*****.**"], "title": ["The man"]}
#
#        resp_str = "%s" % self.server.create_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.authn_request_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'],
#                                       'surName': ['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
#        self.server.close_shelve_db()
コード例 #14
0
 def _parse_logout_request(self, enc_request):
     xmlstr = decode_base64_and_inflate(urllib.unquote(enc_request))
     return logout_request_from_string(xmlstr)
コード例 #15
0
 def test_Saml_logout(self):
     not_on_or_after = time.time() + 3600
     identity = {
         'id-1': {
             'https://sso.example.com/idp/metadata': (not_on_or_after, {
                 'authn_info': [],
                 'name_id': 'id-1',
                 'not_on_or_after': not_on_or_after,
                 'came_from': '/next',
                 'ava': {
                     'uid': ['123456']
                 }
             })
         }
     }
     # modifying config in this test, make copy so as not to effect
     # following tests.
     tmp_sp_config = copy.deepcopy(sp_config)
     with self.app.test_request_context('/', method='GET'):
         sp = auth.Saml(tmp_sp_config)
         # first need to be logged in, let's pretend
         session['_saml_identity'] = identity
         session['_saml_subject_id'] = 'id-1'
         resp = sp.logout(next_url='/next')
         self.assertEqual(resp.status_code, 302)
         self.assert_("SAMLRequest" in resp.headers['Location'])
         url = urlparse.urlparse(resp.headers['Location'])
         self.assertEqual(url.hostname, 'sso.example.com')
         self.assertEqual(url.path, '/idp/slo')
         params = urlparse.parse_qs(url.query)
         self.assert_('SAMLRequest' in params)
         logout = samlp.logout_request_from_string(
             decode_base64_and_inflate(params['SAMLRequest'][0]))
         self.assertEqual(logout.destination,
                          'https://sso.example.com/idp/slo')
         self.assertEqual(logout.name_id.text, 'id-1')
         self.assertIsNotNone(logout.signature)
         # check the caches still contain data
         self.assertEqual(session['_saml_identity'], identity)
         self.assertEqual(session['_saml_subject_id'], 'id-1')
         # verify state cache
         self.assert_(logout.id in session['_saml_state'])
         self.assertEqual(session['_saml_state'][logout.id]['entity_id'],
                          'https://sso.example.com/idp/metadata')
         self.assertEqual(session['_saml_state'][logout.id]['operation'],
                          'SLO')
         self.assertEqual(session['_saml_state'][logout.id]['subject_id'],
                          'id-1')
         self.assertEqual(session['_saml_state'][logout.id]['return_to'],
                          '/next')
         self.assertTrue(session['_saml_state'][logout.id]['sign'])
     # test unsigned logout request
     with self.app.test_request_context('/', method='GET'):
         tmp_sp_config['key_file'] = None
         tmp_sp_config['service']['sp']['logout_requests_signed'] = 'false'
         sp = auth.Saml(tmp_sp_config)
         # first need to be logged in, let's pretend
         session['_saml_identity'] = identity
         session['_saml_subject_id'] = 'id-1'
         resp = sp.logout(next_url='/next')
         self.assertEqual(resp.status_code, 302)
         self.assert_("SAMLRequest" in resp.headers['Location'])
         url = urlparse.urlparse(resp.headers['Location'])
         params = urlparse.parse_qs(url.query)
         self.assert_('SAMLRequest' in params)
         logout = samlp.logout_request_from_string(
             decode_base64_and_inflate(params['SAMLRequest'][0]))
         self.assertIsNone(logout.signature)
         # verify state cache shows signing off
         self.assertFalse(session['_saml_state'][logout.id]['sign'])
コード例 #16
0
ファイル: test_saml.py プロジェクト: dellintosh/flask_pysaml2
 def test_Saml_logout(self):
     not_on_or_after = time.time()+3600
     identity = {'id-1': {
         'https://sso.example.com/idp/metadata': (
             not_on_or_after, {
                 'authn_info': [],
                 'name_id': 'id-1',
                 'not_on_or_after': not_on_or_after,
                 'came_from': '/next',
                 'ava': {'uid': ['123456']}
             }
         )
     }}
     # modifying config in this test, make copy so as not to effect
     # following tests.
     tmp_sp_config = copy.deepcopy(sp_config)
     with self.app.test_request_context('/',
             method='GET'):
         sp = auth.Saml(tmp_sp_config)
         # first need to be logged in, let's pretend
         session['_saml_identity'] = identity
         session['_saml_subject_id'] = 'id-1'
         resp = sp.logout(next_url='/next')
         self.assertEqual(resp.status_code, 302)
         self.assert_("SAMLRequest" in resp.headers['Location'])
         url = urlparse.urlparse(resp.headers['Location'])
         self.assertEqual(url.hostname, 'sso.example.com')
         self.assertEqual(url.path, '/idp/slo')
         params = urlparse.parse_qs(url.query)
         self.assert_('SAMLRequest' in params)
         logout = samlp.logout_request_from_string(
             decode_base64_and_inflate(params['SAMLRequest'][0]))
         self.assertEqual(logout.destination,
             'https://sso.example.com/idp/slo')
         self.assertEqual(logout.name_id.text, 'id-1')
         self.assertIsNotNone(logout.signature)
         # check the caches still contain data
         self.assertEqual(session['_saml_identity'], identity)
         self.assertEqual(session['_saml_subject_id'], 'id-1')
         # verify state cache
         self.assert_(logout.id in session['_saml_state'])
         self.assertEqual(session['_saml_state'][logout.id]['entity_id'],
             'https://sso.example.com/idp/metadata')
         self.assertEqual(session['_saml_state'][logout.id]['operation'],
             'SLO')
         self.assertEqual(session['_saml_state'][logout.id]['subject_id'],
             'id-1')
         self.assertEqual(session['_saml_state'][logout.id]['return_to'],
             '/next')
         self.assertTrue(session['_saml_state'][logout.id]['sign'])
     # test unsigned logout request
     with self.app.test_request_context('/',
             method='GET'):
         tmp_sp_config['key_file'] = None
         tmp_sp_config['service']['sp']['logout_requests_signed'] = 'false'
         sp = auth.Saml(tmp_sp_config)
         # first need to be logged in, let's pretend
         session['_saml_identity'] = identity
         session['_saml_subject_id'] = 'id-1'
         resp = sp.logout(next_url='/next')
         self.assertEqual(resp.status_code, 302)
         self.assert_("SAMLRequest" in resp.headers['Location'])
         url = urlparse.urlparse(resp.headers['Location'])
         params = urlparse.parse_qs(url.query)
         self.assert_('SAMLRequest' in params)
         logout = samlp.logout_request_from_string(
             decode_base64_and_inflate(params['SAMLRequest'][0]))
         self.assertIsNone(logout.signature)
         # verify state cache shows signing off
         self.assertFalse(session['_saml_state'][logout.id]['sign'])
コード例 #17
0
ファイル: test_51_client.py プロジェクト: datopian/pysaml2
    def test_logout_1(self):
        """ one IdP/AA logout from"""

        # 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": "*****@*****.**"
            }
        }
        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 len(resp) == 1
        assert resp.keys() == entity_ids
        item = resp[entity_ids[0]]
        assert isinstance(item, tuple)
        assert item[0] == [('Content-type', 'text/html')]
        lead = "name=\"SAMLRequest\" value=\""
        body = item[1][3]
        i = body.find(lead)
        i += len(lead)
        j = i + body[i:].find('"')
        info = body[i:j]
        xml_str = base64.b64decode(info)
        #xml_str = decode_base64_and_inflate(info)
        req = logout_request_from_string(xml_str)
        print req
        assert req.reason == "Tired"


#    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"] == True
#
#    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.create_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 = discovery_service_request_url("urn:mace:example.com:saml:roland:sp",
#                                            disc_url)
#        print url
#        assert url == "http://example.com/saml2/idp/disc?entityID=urn%3Amace%3Aexample.com%3Asaml%3Aroland%3Asp"
#
#        url = discovery_service_request_url(
#                            self.client.config.entityid,
#                            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 = 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 = discovery_service_response(url=redirect_url,
#                                               returnIDParam="idpID")
#
#        assert entity_id == "http://example.org/saml2/idp/sso"
#        self.server.close_shelve_db()
#
#    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": ["*****@*****.**"], "title": ["The man"]}
#
#        resp_str = "%s" % self.server.create_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.authn_request_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'],
#                                       'surName': ['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
#        self.server.close_shelve_db()