Example #1
0
    def get_saml_response(self, key_file: Optional[str],
                          cert_file: Optional[str]) -> SAMLResponse:
        """
        Extract and decrypt a SAML response from POST data.

        :param key_file: An optional path to a key to decrypt the response.
        :param cert_file: An optional path to a certificate to verify the response.
        :return: A SAML response.
        """
        raw_response = b64decode(
            self.request.POST.get('SAMLResponse',
                                  '').encode('ascii')).decode('utf-8')
        LOGGER.debug('Raw SAML Response: %s', raw_response)

        try:
            response = SAMLResponse(parse_xml(raw_response),
                                    self.request.POST.get('RelayState'))
        except XMLSyntaxError as e:
            raise ParseError(str(e)) from None

        LOGGER.info(
            '[#%r] Received SAML response: id=%r, issuer=%r, in_response_to_id=%r',
            self.log_id, response.id, response.issuer,
            response.in_response_to_id)

        if cert_file:
            response.verify_response(cert_file)
        if key_file:
            response.decrypt(key_file)
        if cert_file:
            response.verify_assertion(cert_file)
        return response
    def test_verify_response_and_assertion_nia(self):
        with cast(TextIO, (DATA_DIR / 'nia_test_response.xml').open('r')) as f:
            tree = parse_xml(f.read())
            remove_extra_xml_whitespace(tree)

        response = SAMLResponse(tree)
        response.verify_response(NIA_CERT_FILE)
        response.decrypt(KEY_FILE)
        self.assertTrue(response.verify_assertion(NIA_CERT_FILE))
    def test_decrypt(self):
        self.maxDiff = None
        with cast(BinaryIO,
                  (DATA_DIR / 'saml_response_decrypted.xml').open('rb')) as f:
            document_decrypted = f.read()
        with cast(BinaryIO,
                  (DATA_DIR / 'saml_response_encrypted.xml').open('rb')) as f:
            document_encrypted = f.read()

        response = SAMLResponse(parse_xml(document_encrypted))
        self.assertEqual(response.decrypt(KEY_FILE), 1)
        self.assertXMLEqual(
            dump_xml(response.document).decode('utf-8'),
            document_decrypted.decode('utf-8'))
    def test_encrypt_assertion_without_encrypted_assertion_elm(self):
        root = Element(Q_NAMES['saml2p:Response'])
        first_child = SubElement(root, 'FirstChild')
        assertion = SubElement(root, Q_NAMES['saml2:Assertion'])
        SubElement(assertion, Q_NAMES['saml2:Issuer']).text = 'CZ.NIC'
        third_child = SubElement(root, 'ThirdChild')
        response = SAMLResponse((ElementTree(root)))

        # Encryption happened.
        self.assertTrue(
            response.encrypt_assertion(CERT_FILE, XmlBlockCipher.AES256_CBC,
                                       XmlKeyTransport.RSA_OAEP_MGF1P))
        # Order of elements kept.
        self.assertIs(root[0], first_child)
        self.assertIs(root[2], third_child)
        # <Assertion> replaced with <EncryptedAssertion>.
        self.assertEqual(root[1].tag, Q_NAMES['saml2:EncryptedAssertion'])
        self.assertEqual(root[1][0].tag, Q_NAMES['xmlenc:EncryptedData'])
        # Make sure we can decrypt the result.
        self.assertEqual(response.decrypt(KEY_FILE), 1)