Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can i confirm the subscription request HTTP from amazon SNS

I have been searching all over the web and nothing gives a clear answer to confirm the subscription request from amazon SNS. I already send the subscription from the amazon console to my website, but what's next? I am using amazon EC2 as my server with PHP.

like image 321
Fernando Santiago Avatar asked Aug 30 '25 15:08

Fernando Santiago


2 Answers

Before you even configure the HTTP/HTTPS endpoint subscription through AWS management console, you need to make sure that the HTTP or HTTPS endpoint of your PHP web site has the capability to handle the HTTP POST requests that Amazon SNS generates. There are several types of SNS messages: SubscriptionConfirmation, Notification and UnsubscribeConfirmation. Your PHP code needs to get the header x-amz-sns-message-type from request and process it based on the message type. For SubscriptionConfirmation message, your PHP application needs to process the POST message body, which is a JSON document. In order to subscribe the topic, your PHP code needs to visit the "SubscriberURL" specified in the JSON body. Optionally, you should verify the signature to make sure the authenticity of message before subscribing the topic.

You can find more details on AWS documentation: http://docs.aws.amazon.com/sns/latest/dg/SendMessageToHttp.html

like image 179
Lan Avatar answered Sep 14 '25 11:09

Lan


Here is an express application (Node.js) which confirms the SNS subscription:

const express = require('express')
const request = require('request')
// parse urlencoded request bodies into req.body
const bodyParser = require('body-parser')
const app = express()
const port = 8080

app.use(bodyParser.urlencoded({ extended: false }))
app.use(bodyParser.json())

app.post('/', (req, res) => {
  let body = ''

  req.on('data', (chunk) => {
    body += chunk.toString()
  })
  
  req.on('end', () => {
    let payload = JSON.parse(body)
    
    if (payload.Type === 'SubscriptionConfirmation') {
      const promise = new Promise((resolve, reject) => {
        const url = payload.SubscribeURL
        
        request(url, (error, response) => {
          if (!error && response.statusCode == 200) {
            console.log('Yess! We have accepted the confirmation from AWS')
            return resolve()
          } else {
            return reject()
          }
        })
      })

      promise.then(() => {
        res.end("ok")
      })
    }
  })
})

app.listen(port, () => console.log('Example app listening on port ' + port + '!'))

To use it one needs to install required packages:

yarn add express request body-parser

Once you confirm the subscription AWS will send a POST request to the server with the following content:

{
  "Type": "SubscriptionConfirmation",
  "MessageId": "XXXXXXXX-1ee3-4de3-9c69-XXXXXXXXXXXX",
  "Token": "SECRET_TOKEN",
  "TopicArn": "arn:aws:sns:us-west-2:XXXXXXXXXXXX:ses-test",
  "Message": "You have chosen to subscribe to the topic arn:aws:sns:us-west-2:XXXXXXXXXXXX:ses-test. To confirm the subscription, visit the SubscribeURL included in this message.",
  "SubscribeURL": "https://sns.us-west-2.amazonaws.com/?Action=ConfirmSubscription&TopicArn=arn:aws:sns:us-west-2:XXXXXXXXXXXX:ses-test&Token=SECRET_TOKEN",
  "Timestamp": "2018-11-21T19:48:08.170Z",
  "SignatureVersion": "1",
  "Signature": "SECRET",
  "SigningCertURL": "https://sns.us-west-2.amazonaws.com/SimpleNotificationService-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX.pem"
}

The payload contains SubscribeURL which is requested by the server.

like image 23
czerasz Avatar answered Sep 14 '25 12:09

czerasz