Пример #1
0
 def test_authn_request_http_redirect_right_signature(self):
     xml_message = generate_authn_request()
     pkey = open(os.path.join(DATA_DIR, 'sp.key'), 'rb').read()
     query_string = sign_http_redirect(xml_message,
                                       pkey,
                                       req_type='SAMLRequest')
     self.assertEqual(len(self.idp_server.ticket), 0)
     self.assertEqual(len(self.idp_server.responses), 0)
     response = self.test_client.get('/sso-test?{}'.format(query_string),
                                     follow_redirects=True)
     self.assertEqual(response.status_code, 200)
     response_text = response.get_data(as_text=True)
     self.assertIn(
         '<form class="Form Form--spaced u-margin-bottom-l " name="login" method="post" action="/login">',
         response_text)
     self.assertEqual(len(self.idp_server.ticket), 1)
     self.assertEqual(len(self.idp_server.responses), 0)
     key = list(self.idp_server.ticket.keys())[0]
     xmlstr = SAMLTree(self.idp_server.ticket[key]._xml_doc)
     xml_message = ET.fromstring(xml_message)
     xml_message = SAMLTree(xml_message)
     self.assertEqual(xml_message.id, xmlstr.id)
Пример #2
0
 def single_logout_service(self):
     """
     SLO endpoint
     """
     try:
         spid_request = self._parse_message(action='logout')
         issuer_name = spid_request.saml_tree.issuer.text
         _slo = self._sp_single_logout_service(issuer_name)
         if _slo is None:
             self._raise_error(
                 'Impossibile trovare un servizio di'
                 ' Single Logout per il service provider {}'.format(
                     issuer_name))
         response_binding = _slo.get('Binding')
         logger.info('Response binding: \n{}'.format(response_binding))
         destination = _slo.get('Location')
         response = create_logout_response(
             {
                 'logout_response': {
                     'attrs': {
                         'in_response_to': spid_request.saml_tree.id,
                         'destination': destination
                     }
                 },
                 'issuer': {
                     'attrs': {
                         'name_qualifier': 'something',
                     },
                     'text': self._config.entity_id
                 }
             }, {
                 'status_code': STATUS_SUCCESS
             }).to_xml()
         relay_state = spid_request.data.relay_state or ''
         if response_binding == BINDING_HTTP_POST:
             response = sign_http_post(response,
                                       self._config.idp_key,
                                       self._config.idp_certificate,
                                       message=True,
                                       assertion=False)
             rendered_template = render_template(
                 'form_http_post.html', **{
                     'action': destination,
                     'relay_state': relay_state,
                     'message': base64.b64encode(response).decode('ascii'),
                     'message_type': 'SAMLResponse'
                 })
             return rendered_template, 200
         elif response_binding == BINDING_HTTP_REDIRECT:
             query_string = sign_http_redirect(
                 response,
                 self._config.idp_key,
                 relay_state,
             )
             location = '{}?{}'.format(destination, query_string)
             if location:
                 return redirect(location)
     except RequestParserError as err:
         self._raise_error(err.args[0])
     except SignatureVerificationError as err:
         self._raise_error(err.args[0])
     except UnknownEntityIDError as err:
         self._raise_error(err.args[0])
     except DeserializationError as err:
         return self._handle_errors(err.initial_data, err.details)
     except MetadataLoadError as err:
         self._raise_error(err.args[0])
     abort(400)
Пример #3
0
 def test_sign_http_redirect(self):
     # https://github.com/italia/spid-testenv2/issues/175
     response_xmlstr = create_response(
         {
             'response': {
                 'attrs': {
                     'in_response_to': 'test_3210',
                     'destination': 'http://redirect'
                 }
             },
             'issuer': {
                 'attrs': {
                     'name_qualifier': 'http://test_id.entity',
                 },
                 'text': 'http://test_id.entity'
             },
             'name_id': {
                 'attrs': {
                     'name_qualifier': 'http://test_id.entity',
                 }
             },
             'subject_confirmation_data': {
                 'attrs': {
                     'recipient': 'http://test_id.entity',
                 }
             },
             'audience': {
                 'text': 'http://test_sp_id.entity',
             },
             'authn_context_class_ref': {
                 'text': SPID_LEVEL_1
             }
         }, {
             'status_code': STATUS_SUCCESS
         }, {}).to_xml()
     with open(os.path.join(DATA_DIR, 'test.key'),
               'r') as fp, open(os.path.join(DATA_DIR, 'test.crt'),
                                'r') as fp2:
         pkey = fp.read().encode('utf-8')
         cert = fp2.read().encode('utf-8')
         verifier = RSA_VERIFIERS[SIG_RSA_SHA256]
         # No relay state
         url = sign_http_redirect(response_xmlstr, pkey, relay_state=None)
         query = parse_qs(url)
         self.assertIn('Signature', query)
         self.assertIn('SigAlg', query)
         self.assertNotIn('RelayState', query)
         self.assertIn('SAMLResponse', query)
         saml_response = query.get('SAMLResponse')[0]
         sig_alg = query.get('SigAlg')[0]
         signature = query.get('Signature')[0]
         signature = b64decode(signature)
         signed_data = '&'.join([
             urlencode({'SAMLResponse': saml_response}),
             urlencode({'SigAlg': sig_alg})
         ])
         signed_data = signed_data.encode('ascii')
         verified = verifier.verify(
             load_pem_x509_certificate(
                 cert, backend=default_backend()).public_key(),
             bytes(signed_data), bytes(signature))
         self.assertTrue(verified)
         # No relay state (2)
         url = sign_http_redirect(response_xmlstr, pkey, relay_state='')
         query = parse_qs(url)
         self.assertIn('Signature', query)
         self.assertIn('SigAlg', query)
         self.assertNotIn('RelayState', query)
         self.assertIn('SAMLResponse', query)
         saml_response = query.get('SAMLResponse')[0]
         sig_alg = query.get('SigAlg')[0]
         signature = query.get('Signature')[0]
         signature = b64decode(signature)
         signed_data = '&'.join([
             urlencode({'SAMLResponse': saml_response}),
             urlencode({'SigAlg': sig_alg})
         ])
         signed_data = signed_data.encode('ascii')
         verified = verifier.verify(
             load_pem_x509_certificate(
                 cert, backend=default_backend()).public_key(),
             bytes(signed_data), bytes(signature))
         self.assertTrue(verified)
         # with relay state
         url = sign_http_redirect(response_xmlstr,
                                  pkey,
                                  relay_state='somevalue')
         query = parse_qs(url)
         self.assertIn('Signature', query)
         self.assertIn('SigAlg', query)
         self.assertIn('RelayState', query)
         self.assertIn('SAMLResponse', query)
         saml_response = query.get('SAMLResponse')[0]
         sig_alg = query.get('SigAlg')[0]
         signature = query.get('Signature')[0]
         relay_state = query.get('RelayState')[0]
         signature = b64decode(signature)
         signed_data = '&'.join([
             urlencode({'SAMLResponse': saml_response}),
             urlencode({'RelayState': relay_state}),
             urlencode({'SigAlg': sig_alg})
         ])
         signed_data = signed_data.encode('ascii')
         verified = verifier.verify(
             load_pem_x509_certificate(
                 cert, backend=default_backend()).public_key(),
             bytes(signed_data), bytes(signature))
         self.assertTrue(verified)
Пример #4
0
    def single_logout_service(self):
        """
        SLO endpoint
        """

        self.app.logger.debug("req: '%s'", request)
        try:
            spid_request = self._parse_message(action='logout')
            issuer_name = spid_request.saml_tree.issuer.text
            # TODO: retrieve the following data from some custom structure
            _slo = self._sp_single_logout_service(issuer_name)
            if _slo is None:
                self._raise_error(
                    'Impossibile trovare un servizio di'\
                    ' Single Logout per il service provider {}'.format(
                        issuer_name
                    )
                )
            response_binding = _slo[0].get('binding')
            self.app.logger.debug(
                'Response binding: \n{}'.format(
                    response_binding
                )
            )
            destination = _slo[0].get('location')
            response = create_logout_response(
                {
                    'logout_response': {
                        'attrs': {
                            'in_response_to': spid_request.saml_tree.id,
                            'destination': destination
                        }
                    },
                    'issuer': {
                        'attrs': {
                            'name_qualifier': 'something',
                        },
                        'text': self.server.config.entityid
                    }
                },
                {
                    'status_code': STATUS_SUCCESS
                }
            ).to_xml()
            key_file = self.server.config.key_file
            cert_file = self.server.config.cert_file
            key = open(key_file, 'rb').read()
            cert = open(cert_file, 'rb').read()
            relay_state = spid_request.data.relay_state or ''
            if response_binding == BINDING_HTTP_POST:
                response = sign_http_post(
                    response, key, cert,
                    message=True, assertion=False
                )
                rendered_template = render_template(
                    'form_http_post.html',
                    **{
                        'action': destination,
                        'relay_state': relay_state,
                        'message': response,
                        'message_type': 'SAMLResponse'
                    }
                )
                return rendered_template, 200
            elif response_binding == BINDING_HTTP_REDIRECT:
                query_string = sign_http_redirect(response, key, relay_state)
                location = '{}?{}'.format(destination, query_string)
                if location:
                    return redirect(location)
        except RequestParserError as err:
            self._raise_error(err.args[0])
        except SignatureVerificationError as err:
            self._raise_error(err.args[0])
        except UnknownEntityIDError as err:
            self._raise_error(err.args[0])
        except DeserializationError as err:
            return self._handle_errors(err.initial_data, err.details)
        abort(400)