protected void validateSamlProtocolResponse(final StatusResponseType response, final SAML2MessageContext context,
                                                final SignatureTrustEngine engine) {
        var configContext = context.getConfigurationContext();

        validateSuccess(response.getStatus());

        if (!response.getVersion().equals(SAMLVersion.VERSION_20)) {
            throw new SAMLException("Invalid SAML version assigned to the response " + response.getVersion());
        }

        if (configContext.isWantsResponsesSigned() && response.getSignature() == null) {
            logger.debug(
                "Unable to find a signature on the SAML response returned. Pac4j is configured to enforce "
                    + "signatures on SAML2 responses from identity providers and the returned response\n{}\n"
                    + "does not contain any signature",
                Configuration.serializeSamlObject(response));

            throw new SAMLSignatureValidationException("Unable to find a signature on the SAML response returned");
        }

        validateSignatureIfItExists(response.getSignature(), context, engine);

        validateIssueInstant(response.getIssueInstant());

        AuthnRequest request = null;
        val messageStorage = context.getSamlMessageStore();
        if (messageStorage != null && response.getInResponseTo() != null) {
            val xmlObject = messageStorage.get(response.getInResponseTo());
            if (xmlObject.isEmpty()) {
                throw new SAMLInResponseToMismatchException(
                    "InResponseToField of the Response doesn't correspond to sent message "
                        + response.getInResponseTo());
            } else if (xmlObject.get() instanceof AuthnRequest) {
                request = (AuthnRequest) xmlObject.get();
            } else {
                throw new SAMLInResponseToMismatchException(
                    "Sent request was of different type than the expected AuthnRequest "
                        + response.getInResponseTo());
            }
        }

        val endpoint = Objects.requireNonNull(context.getSAMLEndpointContext().getEndpoint());

        final List<String> expected = new ArrayList<>();
        if (endpoint.getLocation() != null) {
            expected.add(endpoint.getLocation());
        }
        if (endpoint.getResponseLocation() != null) {
            expected.add(endpoint.getResponseLocation());
        }

        val isDestinationMandatory = context.getSaml2Configuration().isResponseDestinationAttributeMandatory();
        verifyEndpoint(expected, response.getDestination(), isDestinationMandatory);

        if (request != null) {
            verifyRequest(request, context);
        }

        validateIssuerIfItExists(response.getIssuer(), context);
    }
Validates the SAML protocol response:
- IssueInstant
- Issuer
- StatusCode
- Signature

@param response the response
@param context  the context
@param engine   the engine
pac4j-saml/src/main/java/org/pac4j/saml/sso/impl/SAML2AuthnResponseValidator.java