AWS SNS - Mobile Push Notification Service for Ruby on Rails

AWS SNS - Mobile Push Notification Service for Ruby on Rails

Why we need notification service in Rails?

Ruby on Rails uses mainly HTTP (from v5 socket connections were added) - stateless protocol based on request-response pattern to communicate with frontend clients. Client sends request to the server and receives some response and that’s basically it - simple and powerful. But there are some cases when we want to reverse this communication schema. Sometimes mobile applications business logic requires to push message/notification to them from server. This cannot be done by pure HTTP so we have to use external solution to handle this type of notifications.

Available solutions

One of the most popular tool is rpush gem. It can be used to send notification to many types of clients, it’s also simple to use and free. Unfortunately the cost is maintenance of it. On Rails server there must be separate rpush process which uses some extra resources and time to configure it. In the era of microservices fashion we could try to find better solution.

Amazon SNS Mobile Push Notifications Service seems to be a rational alternative to rpush.

It’s part of Amazon Simple Notification Service which is implementation of sender-topic-subscriber pattern and enables to send notifications not only to mobile clients but also to Amazon SQS, email, SMS or HTTP/S subscribers. Moreover AWS SNS is quite cheap if you compare it to other Amazon Web Services. It costs $1.00 to send one million mobile push notifications ($0.50 per million publishes, plus $0.50 per million mobile push notification deliveries). First 1 million Amazon SNS requests per month are free. Of course costs may vary depend of type of notification and AWS Zone.

AWS SNS service is well described on AWS SNS documentation page.

AWS SNS configuration in AWS Console

Before implementing AWS SNS push functionality in Rails application we have to deal with some plain configuration in AWS Management Console - Amazon Web Services.

On AWS Console we choose proper zone and on services main page in section Messaging we choose SNS. Main service page should appear:

image alt text

Click "Get started" button and on SNS dashboard:

image alt text

Select "Create platform application". Then modal box appears where we choose application name and push notification platform.

image alt text

Connection to Google or Apple notification services requires some credentials.

  • for iOS devices (Apple production/development option) we must generate proper iOS push certificate on iPhone Developer Connection Portal and then upload P12 certificate file with or without password. After upload and validation of P12 file texts areas Certificate and Private key will be automatically filled.

  • for Android platform we need only GCM API key from Google Developer also GCM service has to be enabled.

After passing valid authorization data platform application appears on applications list with ARN string assigned to it:

image alt text

Sending notifications from Ruby

To finally allow to send push notifications to Android or iOS applications we need to install aws-sdk Ruby Gem. Then we need to get two keys from AWS Console: access key and secret key. Thouse keys should be set inside config/initializers/aws.rb with region zone:

Aws.config[:credentials] = Aws::Credentials.new(ENV['AURA_AWS_ACCESS_KEY_ID'], 

                                                ENV['AURS_AWS_SECRET_ACCESS_KEY'])

Aws.config[:region] = 'us-west-2'  

Setting authentication data in AWS console makes implementation of push notifications method quite simple:

  def self.push(platform_application_arn, token, text, push_content,  stub_responses = false)
    sns = Aws::SNS::Client.new(stub_responses: stub_responses) \

    # Determine device -> message recipient
    jasons_endpoint = sns.create_platform_endpoint(
      platform_application_arn: platform_application_arn,
      token: token
    ).endpoint_arn

    # Define a push notification message with metadata
    payload = {
      notification_id: "15",
      aps: { 
        alert: text,
        badge: 1,
        sound: "default"
      }, 

      push_content: push_content
    }

    # The same message will be sent to production and sandbox    
    message = { 
      APNS: payload.to_json,
      APNS_SANDBOX: payload.to_json
    }.to_json

    # Pushing message to device through endpoint 
    resp = sns.publish(
      target_arn: jasons_endpoint,
      message: message,
      message_structure: "json",
    )

  # Some error handling need to be made
  rescue => e
    false
  end    

Method parameters are:

platformapplicationarn - ARN string to identify application from AWS SNS applications list. it’s used to create endpoint e.g: arn:aws:sns:us-west-2:6044379833333:app/APNS/production-application for Apple iOS Prod.

token - Unique identifier created by the notification service for an app on a device. The specific name for Token will vary, depending on which notification service is being used. For example, when using APNS as the notification service, you need the device token. Alternatively, when using GCM or ADM, the device token equivalent is called the registration ID.

text - text message that will be sent to mobile device.

push_content - some extra data in hash format that will be sent with text message to mobile device.

stub_responses - parameter which determines if we creating fake requests for tests purposes, default false.