Code Monkey home page Code Monkey logo

aws-php-sns-message-validator's Introduction

Amazon SNS Message Validator for PHP

@awsforphp on Twitter Total Downloads Build Status Apache 2 License

The Amazon SNS Message Validator for PHP library allows you to validate that incoming HTTP(S) POST messages are valid Amazon SNS notifications. This library is standalone and does not depend on the AWS SDK for PHP or Guzzle; however, it does require PHP 5.4+ and that the OpenSSL PHP extension is installed.

Jump To:

Basic Usage

To validate a message, you can instantiate a Message object from the POST data using the Message::fromRawPostData. This reads the raw POST data from the php://input stream, decodes the JSON data, and validates the message's type and structure.

Next, you must create an instance of MessageValidator, and then use either the isValid() or validate(), methods to validate the message. The message validator checks the SigningCertURL, SignatureVersion, and Signature to make sure they are valid and consistent with the message data.

<?php

require 'vendor/autoload.php';

use Aws\Sns\Message;
use Aws\Sns\MessageValidator;
 
$message = Message::fromRawPostData();
 
// Validate the message
$validator = new MessageValidator();
if ($validator->isValid($message)) {
   // do something with the message
}

Installation

The SNS Message Validator can be installed via Composer.

composer require aws/aws-php-sns-message-validator

Getting Help

Please use these community resources for getting help. We use the GitHub issues for tracking bugs and feature requests and have limited bandwidth to address them.

About Amazon SNS

Amazon Simple Notification Service (Amazon SNS) is a fast, fully-managed, push messaging service. Amazon SNS can deliver messages to email, mobile devices (i.e., SMS; iOS, Android and FireOS push notifications), Amazon SQS queues,and โ€” of course โ€” HTTP/HTTPS endpoints.

With Amazon SNS, you can setup topics to publish custom messages to subscribed endpoints. However, SNS messages are used by many of the other AWS services to communicate information asynchronously about your AWS resources. Some examples include:

  • Configuring Amazon Glacier to notify you when a retrieval job is complete.
  • Configuring AWS CloudTrail to notify you when a new log file has been written.
  • Configuring Amazon Elastic Transcoder to notify you when a transcoding job changes status (e.g., from "Progressing" to "Complete")

Though you can certainly subscribe your email address to receive SNS messages from service events like these, your inbox would fill up rather quickly. There is great power, however, in being able to subscribe an HTTP/HTTPS endpoint to receive the messages. This allows you to program webhooks for your applications to easily respond to various events.

Handling Messages

Confirming a Subscription to a Topic

In order to handle a SubscriptionConfirmation message, you must use the SubscribeURL value in the incoming message:

use Aws\Sns\Message;
use Aws\Sns\MessageValidator;
use Aws\Sns\Exception\InvalidSnsMessageException;

// Instantiate the Message and Validator
$message = Message::fromRawPostData();
$validator = new MessageValidator();

// Validate the message and log errors if invalid.
try {
   $validator->validate($message);
} catch (InvalidSnsMessageException $e) {
   // Pretend we're not here if the message is invalid.
   http_response_code(404);
   error_log('SNS Message Validation Error: ' . $e->getMessage());
   die();
}

// Check the type of the message and handle the subscription.
if ($message['Type'] === 'SubscriptionConfirmation') {
   // Confirm the subscription by sending a GET request to the SubscribeURL
   file_get_contents($message['SubscribeURL']);
}

Receiving a Notification

To receive a notification, use the same code as the preceding example, but check for the Notification message type.

if ($message['Type'] === 'Notification') {
   // Do whatever you want with the message body and data.
   echo $message['MessageId'] . ': ' . $message['Message'] . "\n";
}

The message body will be a string, and will hold whatever data was published to the SNS topic.

Unsubscribing

Unsubscribing looks the same as subscribing, except the message type will be UnsubscribeConfirmation.

if ($message['Type'] === 'UnsubscribeConfirmation') {
    // Unsubscribed in error? You can resubscribe by visiting the endpoint
    // provided as the message's SubscribeURL field.
    file_get_contents($message['SubscribeURL']);
}

Testing Locally

One challenge of using webhooks in a web application is testing the integration with the service. Testing integrations with SNS notifications can be fairly easy using tools like ngrok and PHP's built-in webserver. One of our blog posts, Testing Webhooks Locally for Amazon SNS, illustrates a good technique for testing.

NOTE: The code samples in the blog post are specific to the message validator in Version 2 of the SDK, but can be easily adapted to using this version.

Special Thank You

A special thanks goes out to Julian Vidal who helped create the initial implementation in Version 2 of the AWS SDK for PHP.

Contributing

We work hard to provide a high-quality and useful SDK for our AWS services, and we greatly value feedback and contributions from our community. Please review our contributing guidelines before submitting any issues or pull requests to ensure we have all the necessary information to effectively respond to your bug report or contribution.

aws-php-sns-message-validator's People

Contributors

arubacao avatar benmorel avatar cjyclaire avatar diehlaws avatar howardlopez avatar hyandell avatar iquito avatar jeremeamia avatar jeskew avatar jmklix avatar kellertk avatar khushail avatar kstich avatar martinbean avatar nbouvrette avatar parkerram avatar ranvaknin avatar sandervanhooft avatar siwinski avatar smhg avatar stobrien89 avatar yenfryherrerafeliz avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aws-php-sns-message-validator's Issues

Split up missing and invalid certificate errors

The Cannot get the public key from the certificate. error gets thrown in these circumstances:

  • When openssl_pkey_get_public can't extract the key and returns false.
  • When the certClient can't read the certificate.

The latter happens fairly regularly because of network issues. When using the default certClient (file_get_contents) the $certificate variable will contain false (and a PHP Warning will get logged).
Could this get checked separately from the first circumstance?

A possible issue is a custom certClient which returns something different.
On the other hand, having $certificate === false throw a separate error sounds quite harmless.

I'm happy to send a PR if this sounds good.

Most SNS Notifications won't pass validation

SNS Notifications that come from, for example, SES (like complaints and bounce notifications), don't have a 'Message' key/object at the root of the JSON payload. The same goes for 'MessageId', 'Timestamp', etc.
Elastic Transcoder messages can have the same missing fields.

This will result in the Message class to not pass the given JSON object, before it even goes to validation.

The required fields can be found in Message.php, line 11.
The Exception that gets thrown can be found in Message.php, line 151.

How to reproduce: Simply receive an SNS notification using:
$message = Message::fromRawPostData();

Split project is confusing to find

The official SDK docs don't make any mention that these classes are in a separate package. It's especially confusing with the exception classes being in the core SDK, and most other services being in the core SDK as well. Perhaps this isn't just a docs update, but should be a dependency of the core SDK? If the point of the split package is to not force the SDK and Guzzle onto clients, then making this a dependency of the SDK doesn't seem like a big deal.

PHP 8.1 Compatibility

Please fill out the sections below to help us address your issue.

Version of AWS SDK for PHP?

N/A

Version of Amazon SNS Message Validator for PHP?

1.6.0

Version of PHP (php -v)?

8.1rc1

What issue did you see?

PHP Fatal error: During inheritance of ArrayAccess: Uncaught ErrorException: Return type of Aws\Sns\Message::offsetExists($key) should either be compatible with ArrayAccess::offsetExists(mixed $offset): bool, or the #[\ReturnTypeWillChange] attribute should be used to temporarily suppress the notice in /home/runner/work/laravel-aws-sns/laravel-aws-sns/vendor/aws/aws-php-sns-message-validator/src/Message.php:100

Steps to reproduce

This is a run-time failure due to a signature validation error any time the method is invoked.

Additional context

We identified this issue when attempting to validate a package using the message validator against PHP 8.1rc1. We will be submitting a pull request in the future to resolve this issue.

SNS message type header not provided in request header

As per the fromRawPostData() function, it required HTTP_X_AMZ_SNS_MESSAGE_TYPE' but AWS is sending X-Amz-Sns-Message-Type in the header.

public static function fromRawPostData()
{
       // Make sure the SNS-provided header exists.
       if (!isset($_SERVER['HTTP_X_AMZ_SNS_MESSAGE_TYPE'])) {
       throw new \RuntimeException('SNS message type header not provided.');
}

as per Documentation SNS DOC current header is X-Amz-Sns-Message-Type.
Thank You.

PHP Fatal error: Uncaught RuntimeException: SNS message type header not provided.

Please fill out the sections below to help us address your issue.

Version of AWS SDK for PHP?

"aws/aws-sdk-php": "~2.6.0",

Version of Amazon SNS Message Validator for PHP?

"aws/aws-php-sns-message-validator": "^1.6"

Version of PHP (php -v)?

PHP 7.2.34

What issue did you see?

when executing I get the following message:

PHP Fatal error: Uncaught RuntimeException: SNS message type header not provided. in /var/www/vhosts/studio/vendor/aws/aws-php-sns-message-validator/src/Message.php:40
Stack trace:

0 /var/www/vhosts/studio/index.php(8): Aws \ Sns \ Message :: fromRawPostData ()

1 {main}

thrown in /var/www/vhosts/studio/vendor/aws/aws-php-sns-message-validator/src/Message.php on line 40

Steps to reproduce

If you have a runnable example, please include it as a snippet or link to a repository/gist for larger code examples.

I install sdk through composer, and I send it to call in an index.php file, is:

require 'vendor/autoload.php';

use Aws\Sns\Message;
use Aws\Sns\MessageValidator;
use Aws\Sns\Exception\InvalidSnsMessageException;

// Instantiate the Message and Validator
$message = Message::fromRawPostData();
$validator = new MessageValidator();

// Validate the message and log errors if invalid.
try {
   $validator->validate($message);
} catch (InvalidSnsMessageException $e) {
   // Pretend we're not here if the message is invalid.
   http_response_code(404);
   error_log('SNS Message Validation Error: ' . $e->getMessage());
   die();
}

// Check the type of the message and handle the subscription.
if ($message['Type'] === 'SubscriptionConfirmation') {
   // Confirm the subscription by sending a GET request to the SubscribeURL
   file_get_contents($message['SubscribeURL']);
}

Additional context

Any additional information relevant to the issue. Examples include any framework you may be using (e.g. Laravel, Wordpress) in conjunction with the AWS SDK for PHP, or PHP/environment config settings if the issue is related to memory or performance.

Message Provenance

Given the SigningCertURL is read from the message itself, what's to stop a bad actor from crafting a malicious message and self-signing it?

SNS message type header not provided.

Hi,

First of all I wanna thank you for sharing the code with us.

But when I run the code i get the following error:

Fatal error: Uncaught exception 'RuntimeException' with message 'SNS message type header not provided.' in /home/communiq/domains/millows.communiq.nl/public_html/aws/vendor/aws/aws-php-sns-message-validator/src/Message.php:33

Stack trace: #0 /home/communiq/domains/millows.communiq.nl/public_html/aws/SimpleNotificationService.php(46): Aws\Sns\Message::fromRawPostData() #1 {main} thrown in /home/communiq/domains/millows.communiq.nl/public_html/aws/vendor/aws/aws-php-sns-message-validator/src/Message.php on line 33

The subscription is already confirmed..

Could you please help me out here?

Basic curl implementation

Please add it to the README.

function curl_get_contents( $url ) {

    if ( ! function_exists( 'curl_init' ) ) {
        return false;
    }

    $ch = curl_init();
    $timeout = 60;

    curl_setopt( $ch, CURLOPT_URL, $url );
    curl_setopt( $ch, CURLOPT_CONNECTTIMEOUT, $timeout );
    curl_setopt( $ch, CURLOPT_RETURNTRANSFER, true );
    $response = curl_exec( $ch );
    curl_close( $ch );

    return $response;
}

// Instantiate the Message and Validator
$message = Message::fromRawPostData();
$validator = new MessageValidator( 'curl_get_contents' );

Support for psr/http-message 2.0

Describe the bug

This package can't not be installed on existing projects which require psr/http-message 2.0

Expected Behavior

Package to be installed within projects which depend on psr/http-message 2.0

Current Behavior

composer require aws/aws-php-sns-message-validator failes with below error

aws/aws-php-sns-message-validator[1.5.0, ..., 1.8.0] require psr/http-message ^1.0 -> found psr/http-message[1.0, 1.0.1, 1.1] but the package is fixed to 2.0 (lock file version) by a partial update and that version does not match.

Reproduction Steps

Install the package along with psr/http-message 2.0 as root requirement

Possible Solution

Update the dependency or maybe remove it? See below PR

#56

Additional Information/Context

No response

SDK version used

n/a

Environment details (OS name and version, etc.)

n/a

Error: "Message" is required to verify the SNS Message

Same error of that mentioned in #29, this issue has plagued me as well, in particular when sending SNS Notifications via Elastic Transcoder. Elastic Transcoder Notification payloads don't seem to contain a "Message" field. Is there any work around's to this?

Here is an example of an Elastic Transcoder Notification, recieved via E-Mail:

{
  "state" : "COMPLETED",
  "version" : "2012-09-25",
  "jobId" : "1559924750698-dejdio",
  "pipelineId" : "1559968916611-abcdef",
  "input" : {
    "key" : "MySong.mp3",
    "container" : "auto"
  },
  "inputCount" : 1,
  "outputs" : [ {
    "id" : "1",
    "presetId" : "1351620000001-100110",
    "key" : "MySong.m4a",
    "thumbnailPattern" : "",
    "rotate" : "auto",
    "status" : "Complete",
    "duration" : 157
  } ]
}

Allow Aws\Sns\Message

Allow usage of Aws\Sns\Messageinstead of limiting to Aws\Sns\MessageValidator\Message.
This should be essentially the same.

Can be fixed by moving the typecheck into the method.
Do you want me to send a pull-request?

Installing from Source

Hi -

Thanks for this validator. My endpoints have been operating manually without the SDK for some time and i really want to get a validator back online. I am getting constant errors when i try to install this through composer, and i am looking for some guidance on where to install it if i am going to install it from the source.

Please let me know if this makes sense when you have a chance.

Push Notification implementation

I am looking for a sample code or project , which uses AWS PHP sdk to send "In app notification" on ios and android using SNS

I got lots of examples for simple text messages sending and subscription confirmation etc, but haven't come across anything that details out the "Push notifications on mobile devices"

Is there anything ?

failed to open stream

This is an issue with my host setup, but hoping someone can steer me in the right direction. I'm seeing the following warnings in my logs. Lots of chatter about missing ca certificates possibly? I'm running centos CentOS Linux release 7.3 and AWS php sdk 3.29.7.

Somehow the SNS still appears to be processed, but how do I fix my setup here?

InvalidSnsMessageException: Cannot get the certificate from

Version of Amazon SNS Message Validator for PHP?

1.6.0

Version of PHP (php -v)?

php 7.4

What issue did you see?

Uncaught PHP Exception Aws\Sns\Exception\InvalidSnsMessageException: "Cannot get the certificate from "https://sns.eu-west-1.amazonaws.com/SimpleNotificationService-xxxxx.pem"." at /my_project/vendor/aws/aws-php-sns-message-validator/src/MessageValidator.php line 92

Steps to reproduce

It works well with ngrok locally but I cannot understand the error origin in production.
It should be related to my php configuration but I don't know what.
allow_url_open is enabled and curl extension as well

If I run this, I can read the certificate:
php -r "var_dump(file_get_contents('https://sns.eu-west-1.amazonaws.com/SimpleNotificationService-xxxx.pem'));";

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.