def _parse_response(self, xmlstr, response_cls, service, binding,
                        outstanding_certs=None, **kwargs):
        """ Deal with a Response

        :param xmlstr: The response as a xml string
        :param response_cls: What type of response it is
        :param binding: What type of binding this message came through.
        :param outstanding_certs: Certificates that belongs to me that the
                IdP may have used to encrypt a response/assertion/..
        :param kwargs: Extra key word arguments
        :return: None if the reply doesn't contain a valid SAML Response,
            otherwise the response.
        """

        if self.config.accepted_time_diff:
            kwargs["timeslack"] = self.config.accepted_time_diff

        if "asynchop" not in kwargs:
            if binding in [BINDING_SOAP, BINDING_PAOS]:
                kwargs["asynchop"] = False
            else:
                kwargs["asynchop"] = True

        response = None
        if not xmlstr:
            return response

        if "return_addrs" not in kwargs:
            bindings = {
                BINDING_SOAP,
                BINDING_HTTP_REDIRECT,
                BINDING_HTTP_POST,
            }
            if binding in bindings:
                # expected return address
                kwargs["return_addrs"] = self.config.endpoint(
                        service,
                        binding=binding,
                        context=self.entity_type)

        try:
            response = response_cls(self.sec, **kwargs)
        except Exception as exc:
            logger.info("%s", exc)
            raise

        xmlstr = self.unravel(xmlstr, binding, response_cls.msgtype)
        if not xmlstr:  # Not a valid reponse
            return None

        try:
            response_is_signed = False
            # Record the response signature requirement.
            require_response_signature = response.require_response_signature
            # Force the requirement that the response be signed in order to
            # force signature checking to happen so that we can know whether
            # or not the response is signed. The attribute on the response class
            # is reset to the recorded value in the finally clause below.
            response.require_response_signature = True
            response = response.loads(xmlstr, False, origxml=xmlstr)
        except SigverError as err:
            if require_response_signature:
                logger.error("Signature Error: %s", err)
                raise
            else:
                # The response is not signed but a signature is not required
                # so reset the attribute on the response class to the recorded
                # value and attempt to consume the unpacked XML again.
                response.require_response_signature = require_response_signature
                response = response.loads(xmlstr, False, origxml=xmlstr)
        except UnsolicitedResponse:
            logger.error("Unsolicited response")
            raise
        except Exception as err:
            if "not well-formed" in "%s" % err:
                logger.error("Not well-formed XML")
            raise
        else:
            response_is_signed = True
        finally:
            response.require_response_signature = require_response_signature

        logger.debug("XMLSTR: %s", xmlstr)

        if not response:
            return response

        keys = None
        if outstanding_certs:
            try:
                cert = outstanding_certs[response.in_response_to]
            except KeyError:
                keys = None
            else:
                if not isinstance(cert, list):
                    cert = [cert]
                keys = []
                for _cert in cert:
                    keys.append(_cert["key"])

        try:
            assertions_are_signed = False
            # Record the assertions signature requirement.
            require_signature = response.require_signature
            # Force the requirement that the assertions be signed in order to
            # force signature checking to happen so that we can know whether
            # or not the assertions are signed. The attribute on the response class
            # is reset to the recorded value in the finally clause below.
            response.require_signature = True
            # Verify that the assertion is syntactically correct and the
            # signature on the assertion is correct if present.
            response = response.verify(keys)
        except SignatureError as err:
            if require_signature:
                logger.error("Signature Error: %s", err)
                raise
            else:
                response.require_signature = require_signature
                response = response.verify(keys)
        else:
            assertions_are_signed = True
        finally:
            response.require_signature = require_signature

        # If so configured enforce that either the response is signed
        # or the assertions within it are signed.
        if response.require_signature_or_response_signature:
            if not response_is_signed and not assertions_are_signed:
                msg = "Neither the response nor the assertions are signed"
                logger.error(msg)
                raise SigverError(msg)

        return response
Deal with a Response

        :param xmlstr: The response as a xml string
        :param response_cls: What type of response it is
        :param binding: What type of binding this message came through.
        :param outstanding_certs: Certificates that belongs to me that the
                IdP may have used to encrypt a response/assertion/..
        :param kwargs: Extra key word arguments
        :return: None if the reply doesn't contain a valid SAML Response,
            otherwise the response.