public function receive() : ?Message
    {
        $data = self::parseQuery();
        if (array_key_exists('SAMLRequest', $data)) {
            $message = $data['SAMLRequest'];
        } elseif (array_key_exists('SAMLResponse', $data)) {
            $message = $data['SAMLResponse'];
        } else {
            throw new \Exception('Missing SAMLRequest or SAMLResponse parameter.');
        }

        if (isset($data['SAMLEncoding']) && $data['SAMLEncoding'] !== self::DEFLATE) {
            throw new \Exception('Unknown SAMLEncoding: '.var_export($data['SAMLEncoding'], true));
        }

        $message = base64_decode($message);
        if ($message === false) {
            throw new \Exception('Error while base64 decoding SAML message.');
        }

        $message = gzinflate($message);
        if ($message === false) {
            throw new \Exception('Error while inflating SAML message.');
        }

        $document = DOMDocumentFactory::fromString($message);
        Utils::getContainer()->debugMessage($document->documentElement, 'in');
        if (!$document->firstChild instanceof \DOMElement) {
            throw new \Exception('Malformed SAML message received.');
        }
        $message = Message::fromXML($document->firstChild);

        if (array_key_exists('RelayState', $data)) {
            $message->setRelayState($data['RelayState']);
        }

        if (!array_key_exists('Signature', $data)) {
            return $message;
        }

        if (!array_key_exists('SigAlg', $data)) {
            throw new \Exception('Missing signature algorithm.');
        }

        $signData = [
            'Signature' => $data['Signature'],
            'SigAlg'    => $data['SigAlg'],
            'Query'     => $data['SignedQuery'],
        ];

        $message->addValidator([get_class($this), 'validateSignature'], $signData);

        return $message;
    }