/**
  * @param Request $request
  * @return int
  */
 public function handleRequest(Request $request)
 {
     if (!$request->isMethod('POST')) {
         return 405;
     }
     try {
         $data = json_decode($request->getContent(), true);
         $message = Message::fromArray($data);
         $validator = new MessageValidator();
         $validator->isValid($message);
     } catch (\Exception $e) {
         return 404;
     }
     if (isset($data['Token']) && isset($data['TopicArn'])) {
         $topicArn = $data['TopicArn'];
         $token = $data['Token'];
         $topicEntity = $this->repo->getTopicByArn($topicArn);
         if ($topicEntity instanceof Topic) {
             $topicEntity->setToken($token);
             $this->repo->save($topicEntity);
             $client = $this->clientFactory->getSnsClient();
             $client->confirmSubscription(array('TopicArn' => $topicEntity->getTopicArn(), 'Token' => $topicEntity->getToken()));
             $this->repo->remove($topicEntity);
             return 200;
         }
     }
     return 404;
 }
 /**
  * Validates a message from SNS to ensure that it was delivered by AWS
  *
  * @param Message $message The message to validate
  *
  * @throws CannotGetPublicKeyFromCertificateException If the certificate cannot be retrieved
  * @throws CertificateFromUnrecognizedSourceException If the certificate's source cannot be verified
  * @throws InvalidMessageSignatureException           If the message's signature is invalid
  */
 public function validate(Message $message)
 {
     // Get the cert's URL and ensure it is from AWS
     $certUrl = Url::factory($message->get('SigningCertURL'));
     $this->validateUrl($certUrl);
     // Get the cert itself and extract the public key
     $certificate = $this->client->get((string) $certUrl)->send()->getBody();
     $publicKey = openssl_get_publickey($certificate);
     if (!$publicKey) {
         throw new CannotGetPublicKeyFromCertificateException();
     }
     // Verify the signature of the message
     $stringToSign = $message->getStringToSign();
     $incomingSignature = base64_decode($message->get('Signature'));
     if (!openssl_verify($stringToSign, $incomingSignature, $publicKey, OPENSSL_ALGO_SHA1)) {
         throw new InvalidMessageSignatureException();
     }
 }
 /**
  * Validates a message from SNS to ensure that it was delivered by AWS
  *
  * @param Message $message The message to validate
  *
  * @throws MessageValidatorException If the certificate cannot be
  *     retrieved, if the certificate's source cannot be verified, or if the
  *     message's signature is invalid.
  */
 public function validate(Message $message)
 {
     // Get and validate the URL for the certificate.
     $certUrl = Url::fromString($message->get('SigningCertURL'));
     $this->validateUrl($certUrl);
     // Get the cert itself and extract the public key
     $certificate = $this->client->get((string) $certUrl)->getBody();
     $key = openssl_get_publickey($certificate);
     if (!$key) {
         throw new MessageValidatorException('Cannot get the public key ' . 'from the certificate.');
     }
     // Verify the signature of the message
     $content = $message->getStringToSign();
     $signature = base64_decode($message->get('Signature'));
     if (!openssl_verify($content, $signature, $key, OPENSSL_ALGO_SHA1)) {
         throw new MessageValidatorException('The message signature is ' . 'invalid.');
     }
 }
 public function testValidateSucceedsWhenMessageIsValid()
 {
     // Create a real message
     $message = Message::fromArray(array('Message' => 'foo', 'MessageId' => 'bar', 'Timestamp' => time(), 'TopicArn' => 'baz', 'Type' => 'Notification', 'SigningCertURL' => 'https://foo.amazonaws.com/bar', 'Signature' => ''));
     // Get the signature for a real message
     list($signature, $certificate) = $this->getSignature($message->getStringToSign());
     $message->getData()->set('Signature', $signature);
     // Create the validator with a mock HTTP client that will respond with the certificate
     $client = $this->getMockClient(new Response(200, null, $certificate));
     $validator = new MessageValidator($client);
     // The message should validate
     $this->assertTrue($validator->isValid($message));
 }
 /**
  * @param Request $request
  * @return int
  */
 public function handleRequest(Request $request)
 {
     if (!$request->isMethod('POST')) {
         return 405;
     }
     try {
         $data = json_decode($request->getContent(), true);
         $message = Message::fromArray($data);
         $validator = new MessageValidator();
         $validator->validate($message);
     } catch (\Exception $e) {
         return 404;
         // not valid message, we return 404
     }
     if (isset($data['Message'])) {
         $message = json_decode($data['Message'], true);
         if (!is_null($message)) {
             if (isset($message['notificationType']) && $message['notificationType'] == self::MESSAGE_TYPE_SUBSCRIPTION_SUCCESS) {
                 return 200;
             }
             if (isset($message['notificationType']) && $message['notificationType'] == self::MESSAGE_TYPE_BOUNCE) {
                 foreach ($message['bounce']['bouncedRecipients'] as $bounceRecipient) {
                     $email = $bounceRecipient['emailAddress'];
                     $bounce = $this->repo->findBounceByEmail($email);
                     if ($bounce instanceof Bounce) {
                         $bounce->incrementBounceCounter();
                         $bounce->setLastTimeBounce(new \DateTime());
                         $bounce->setPermanent($message['bounce']['bounceType'] == 'Permanent');
                     } else {
                         $bounce = new Bounce($email, new \DateTime(), 1, $message['bounce']['bounceType'] == 'Permanent');
                     }
                     $this->repo->save($bounce);
                 }
                 return 200;
             }
         }
     }
     return 404;
 }
Beispiel #6
0
 /**
  * @dataProvider getDataForStringToSignTest
  */
 public function testBuildsStringToSignCorrectly(array $messageData, $expectedSubject, $expectedStringToSign)
 {
     $message = new Message(new Collection($messageData));
     $this->assertEquals($expectedSubject, $message->get('Subject'));
     $this->assertEquals($expectedStringToSign, $message->getStringToSign());
 }
 /**
  * Amazon SNS endpoint to receive bounces and complains notified by Amazon SES
  *
  */
 public function mailBounceAction()
 {
     $response = new Response();
     $body = $this->request->getRawBody();
     $data = @json_decode($body, true);
     if (!is_array($data)) {
         return $response;
     }
     $message = Message::fromArray($data);
     $validator = new MessageValidator();
     if ($validator->isValid($message)) {
         $notification = json_decode($message->get('Message'), true);
         if (is_array($notification)) {
             do {
                 if (!isset($notification['notificationType'])) {
                     break;
                 }
                 if ($notification['notificationType'] == 'Bounce') {
                     if (!isset($notification['bounce'])) {
                         break;
                     }
                     $bounce = $notification['bounce'];
                     if (!isset($bounce['bouncedRecipients']) || !is_array($bounce['bouncedRecipients'])) {
                         break;
                     }
                     foreach ($bounce['bouncedRecipients'] as $recipient) {
                         $notificationBounce = new NotificationsBounces();
                         $notificationBounce->email = $recipient['emailAddress'];
                         $notificationBounce->status = $recipient['status'];
                         $notificationBounce->diagnostic = $recipient['diagnosticCode'];
                         $notificationBounce->save();
                     }
                 }
             } while (0);
         }
     }
     return $response;
 }