AWS SNS Push Notifications

Matt McCandless AWS, Cloud, Java, Problem Solving, Technology Snapshot Leave a Comment

Push it, Push it Real Good

Have you ever received endless notifications from the latest application you just downloaded? For example, a bank application that tells you your balance is less than $50. It is likely a message sent directly to your phone through Apple Push Notification Service, Firebase Cloud Messaging, or some other like service.

While you can use any of these services directly, there is a lot to gain by using something like AWS SNS to manage, send, and organize your notifications.

In this post, we show an example of the Push Notification feature of Amazon Simple Notification Service (SNS) using Firebase to handle the iOS and Android messages. Code examples are in Java using Eclipse.

Do note that this blog is solely focused on Push Notification feature of SNS. Keep in mind that SNS can be used for email and SMS messaging, but for brevity, we will steer clear of those.

Introduction to SNS

So what is SNS anyways? Well, Amazon Web Services (AWS) defines it as follows:

  • Amazon Simple Notification Service (SNS) is a highly available, durable, secure, fully managed pub/sub messaging service that enables you to decouple microservices, distributed systems, and serverless applications.
  • Using Amazon SNS topics, your publisher systems can fan out messages to a large number of subscriber endpoints for parallel processing, including Amazon SQS queues, AWS Lambda functions, and HTTP/S webhooks.
  • SNS can be used to fan out notifications to end users using mobile push, SMS, and email.

Image from product site, aws.amazon.com

Push Comes to Shove

To get started in the AWS world you must have an account. Fair warning, most of the things in AWS world will cost you some money. That said, you shouldn’t have any expenditures here unless you begin sending messages on a massive scale. Chances are if you have that kind of following, the cost won’t bother you. What you will need to get started:

  • An AWS account
  • A mobile application (AWS has a testing application you can download)
  • Registration with the mobile platform (application token)
  • Registration of a particular application with a device (platform token)
  • Create the platform application endpoint object with AWS SNS (can be done on AWS console)
  • Create platform endpoint with device and platform application token on AWS SNS
  • All the above leads you to the final step of sending a published message to an endpoint (device)

The easiest way to get started, if you don’t already have a mobile application or not a mobile application developer, is to use the sample application that AWS has. However, it isn’t exactly a masterpiece of code! It is clunky and you’ll have to force stop it so it stops annoying you while trying to check your email or any other applications for that matter.

Here is where you can find it and get it going locally:

Next, you’ll have to register with Firebase (which is now the default for Google Cloud Messaging).

For your implementation of how you want to interact with AWS, you’ll need AWS SDK. It uses a BOM (bill of materials) so that it is a little cleaner when building what you need to use SNS.

 <dependencyManagement>
      <dependencies>
          <dependency>
          <groupId>com.amazonaws</groupId>
          <artifactId>aws-java-sdk-bom</artifactId>
          <version>1.11.327</version>
          <type>pom</type>
          <scope>import</scope>
      </dependency>
      </dependencies>
  </dependencyManagement>...
  <dependency>
      <groupId>com.amazonaws</groupId>
      <artifactId>aws-java-sdk-sns</artifactId>
  </dependency>..

The main things needed from the SDK are as follows:

  • Create a Platform Application
  • Create Device Endpoint
  • Publish Push Notification
  • Update Platform Application Token
  • Update Device Endpoint Token
See Also:  Case Study Published - Blockchain In Hyperledger: Better Than ETL?

The Create Platform Application is the registering of your mobile application and the messaging service using the token provided by the messaging service. When registering it with AWS it creates an endpoint that can be used to identifying your mobile application and messaging service.

Think of an endpoint as a domain name that points to an IP. It’s a little more complicated than that but similar. It is simply a pointer for you to reach your service. All subsequent devices you add must have a platform application as its parent. Removing the platform application removes all the children device endpoints.

private CreatePlatformApplicationResult createPlatformApplication(String applicationName, String platform,
        String principal, String credential)
        throws AuthorizationErrorException, InternalErrorException, InvalidParameterException {

    CreatePlatformApplicationRequest createPlatformApplicationRequest = new CreatePlatformApplicationRequest();
    Map<String, String> attributes = new HashMap<String, String>();
    attributes.put("PlatformPrincipal", principal);
    attributes.put("PlatformCredential", credential);
    createPlatformApplicationRequest.setAttributes(attributes);
    createPlatformApplicationRequest.setName(applicationName);
    createPlatformApplicationRequest.setPlatform(platform);

    return snsClient.createPlatformApplication(createPlatformApplicationRequest);
}

The Create Device Endpoint is the registering of a device that is using the mobile application you have published. It uses a unique token that points only to your phone by using a combination of the device, mobile application, and OS specifics. This allows your device to be pinpointed among all other devices that exist out in the world.

public String createDeviceEndpoint(String customData, String token, String platformAppArn) throws AuthorizationErrorException, InternalErrorException, InvalidParameterException, NotFoundException {
    CreatePlatformEndpointResult result = new CreatePlatformEndpointResult();
    CreatePlatformEndpointRequest request = new CreatePlatformEndpointRequest();
    request.setCustomUserData(customData);
    request.setToken(token);
    request.setPlatformApplicationArn(platformAppArn);
    result  = snsClient.createPlatformEndpoint(request);
    return result.getEndpointArn();
    
}

Publish Push Notification is the ultimate purpose of using SNS. This allows a message to be sent to any single device or any subscribed topics that a phone may be attached to.

SNS Topics (think of a group) have subscribers that want messages related to that topic. Most would refer this to as a pub-sub architecture. The end user subscribes to a published topic, for example, a news update on the market activity of a company. Then, when a published message is sent out to the topic, all subscribers receive the message in real time.

There does not have to be a subscribed topic to send a message to a device. You can send a single message to any device at any time and only that device will receive it. It can be a pretty powerful communication tool.

public PublishResult publish(String arn, Map<String, Map<String, String>> data,
        AwsUtils awsUtils) {
    String platform = "";
    if (data.keySet().iterator().hasNext()) {
        platform = data.keySet().iterator().next();
    }
    
    if (platform.equalsIgnoreCase("")) {
        throw new InvalidParameterException("Must be GCM");
    }
    
    PublishRequest request = new PublishRequest();
    request.setMessageStructure("json");
    Map<String, Object> androidMsg = new HashMap<String, Object>();
    Map<String, String> messageMap = new HashMap<String, String>();
    messageMap.put("text", data.get(platform).get("text"));
    androidMsg.put("data", messageMap);
    String message = jsonify(androidMsg);
    Map<String, String> msgMap = new HashMap<String, String>();
    msgMap.put("GCM", message);
    
    String sendMsg = jsonify(msgMap);    
    request.setTargetArn(arn);
    request.setMessage(sendMsg);    
    return snsClient.publish(request);    
}

The Update Platform Application Token is used whenever a token for your application is changed by the powers that be. Android and iOS reserve the right to change tokens when they feel like it. The same goes for Update Device Endpoint Token. There must be a way to update these tokens on AWS so that the application and device’s identification remains updated.

Pushing Security

AWS utilizes public/private keys for authentication. These are very powerful.

It is highly recommended to create a sub-user that only has the rights to use SNS and a logging ability to use CloudWatch. CloudWatch is a logging mechanism which will greatly help in seeing if a message has been delivered or not.

See Also:  The Wonderful Wide World of webpack: Unpacking Awesomeness

The IAM roles for using CloudWatch gets a little murky so we’ll skip that discussion. It is a case-by-case need. Do not use your root account for using SNS in a production environment. You don’t want someone getting a hold of these keys and then spinning up Bitcoin mining servers.

Pushing Your Narrative

When it comes to sending global messages, all registered devices can be easily subscribed to a topic inside the AWS console. The topic can then have a message published to it and sent on demand. This is a quick and easy way to send out a public message to all users of push notifications on your application.

Pushing messages is fairly inexpensive. The first 1 million requests are free, then $0.50/million after that (as of January 2019). Keep in mind, requests are not the exact message. It is a 64KB chunk of data. Still, you would have to start doing some very heavy messaging on a private level to reach this.

Push You Around

What I found when using the SDK for Java was that Exceptions are not forced to be picked up. You must handle exceptions very well. You will have to review the documentation thoroughly to make sure that you are handling them all well within your implementation.

A key exception is for disabled devices. The messaging services keep track of whether a message is received by a device or not. AWS sends an exception when this occurs upon trying to publish to a device. It is up to the implementer to decide how and what cleanup looks like.

Don’t pull your hair out and don’t cut corners here. You will have a very tough time figuring out issues if you don’t catch exceptions.

Conclusion

This blog is fairly dry mostly because it isn’t all that flashy of a topic. The output is largely text. It can, although, have an immense effect on your small business, side hustle, or charity. Getting people the information they need quickly is vital in this real-time society we live in.

There isn’t much to push here. There are a lot of moving parts to get all of this working. Without diving into a ton of technical detail, this is as far as this blog goes. If you want to dive into understanding all of this more intimately, it really has to be on implementation by implementation basis.

There is no one way to do it correctly. Some key things to think about:

  • How do we keep track of the endpoints that all of our registered devices that want to receive messages?
  • What does our cleanup process look like?
  • How many devices do we allow people to register?
  • How do we securely display the correct notifications to the right people?

Now get out there and push it to your company!

What Do You Think?