The Lambda Blog

Serverless Cloud Guide

Menu
  • Home
  • Categories
  • Projects
  • About Us
  • Privacy Policy
  • Disclaimer
  • Contact
Menu
serverless mobile push notifications with firebase lambda and python using cloudformation

How to integrate Lambda with Firebase to send push notifications using Python

Posted on January 20, 2022August 14, 2022 by user
Navigation » Home » Lambda

Messaging and communication systems are an excellent fit for taking all the advantages of serverless cloud platforms and designs – highly scalable cost effective on demand pay per use infrastructure that can be defined as code without any of the hassles of a more traditional setup. In this blog I have two such full featured example applications – covering serverless emailing and also covering sms text messaging. Naturally, mobile push notifications also fit into this category very well and this post will cover how to do that by using Google’s firebase-admin python sdk with an AWS Lambda. This topic is not a full functionality application integrated with a dynamodb database or a front end user interface but a more concise serverless component that can be integrated as a microservice building block of a larger application – something I plan to cover in future articles.

Do note, this topic is not going to cover setting up a Firebase account to work with a sample app – we will focus on the simply building a Lambda to initialize an existing app using the python sdk and send push notifications.

Defining the Lambda yaml template

Check out this post for a more detailed explanation of working with AWS SAM, Cloudformation and Lambda. The first section below simply outlines the Lambda definition which we will code to send push notifications in the next sections. This Lambda needs to special IAM permissions or anything, though depending on your use case, you might want to consider defining cloudformation parameters to pass in values such as the firebase project id and such to the Lambda as environment variables. In this post those details are going to be hard coded within the Lambda code

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: Sending Mobile Push Notifications with the firebase-admin sdk

Resources:

  FirebasePushLambda:
    Type: AWS::Serverless::Function
    Properties:
      Architectures:
        - arm64
      Runtime: python3.9
      CodeUri: ./firebase-push-lambda/
      Handler: firebase-push-lambda.event_handler
      Description: Send Mobile Push Notifications with the firebase-admin sdk from inputs
      FunctionName: sns-lambda

Creating the Python Lambda directory with the requirements.txt file

As outline above – we need to create a directory for our Lambda which can then be deployed as part of the cloudformation stack. This needs to have the same name as defined in your template yaml – in this case I have used firebase-push-lambda. The actual Lambda is a python file of the same name and the requirements.txt needs to have the dependency to indicate to Cloudformation that we need the firebase-admin sdk packaged along with our Lambda. We also need the pythong init file. The AWS SAM sdk will take care of the build, package and deploy magic as outlined in the post linked earlier.

-firebase-push-lambda
--__init__.py
--firebase-push-lambda.py
--requirements.txt

#inside requirements.txt - add
firebase-admin

Coding the push notification Lambda

Next up, we are going to code the Lambda. The Lambda will accept the basic inputs needed to populate the content of the push notificayion- title, data, body and of course the topic. The credentials certificate needed to initialize the fire-admin api is hard coded – replace with parameters specific to your project. Thinking ahead, depending on how you might consider using this base serverless block as a component for your own application, you might want to consider designs where even the project is dynamic – this would make sense when you have multiple apps you want to send push notifications to.

import firebase_admin
from firebase_admin import messaging
from firebase_admin import credentials
from datetime import timedelta

firebase_credential = {
  "type": "#FILL",
  "project_id": "#FILL",
  "private_key_id": "#FILL",
  "private_key": "#FILL",
  "client_email": "#FILL",
  "client_id": "#FILL",
  "auth_uri": "https://accounts.google.com/o/oauth2/auth",
  "token_uri": "https://oauth2.googleapis.com/token",
  "auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
  "client_x509_cert_url": "#FILL"
}

firebase_admin.initialize_app(credentials.Certificate(firebase_credential))

def event_handler(event, context):

        topic = event["topic"]
        data = event["data"]
        title = event["title"]
        body = event["body"]

        message = messaging.Message(
            android=messaging.AndroidConfig(
                ttl=timedelta(seconds=3600),
                priority='normal',
                notification=messaging.AndroidNotification(),
            ),
            apns=messaging.APNSConfig(
                headers={
                    'apns-priority': '10'
                },
                payload=messaging.APNSPayload(
                    aps=messaging.Aps(
                        alert=messaging.ApsAlert(
                            title=title,
                            body=body,
                        ),
                        mutable_content=True,
                        sound='default'
                    ),
                ),
            ),
            data=data,
            topic=topic,
        )

        messaging.send(message, False)

The Lambda is pretty straightforward but lets break it down anyway.

We need to initialize the firebase admin sdk by passing it the credentials for your project. This can be a file or a python dictionary – which is what I have used. Since this isn’t dynamic it is a good practice to initialize this outside of the Lambda handler function – so AWS can reuse the Lambda for other requests without running through the initialization code each time. This should be how all initializations are done with Lambda – outside the handler.

The Lambda is accepting the events as part of its input payload – as seen where we extract the body, title, data and topic details of the request from the event. The signature changes slightly if you have this fronted by an API gateway, but you get the idea. Lastly, we make use of the messaging api in the sdk to define and send our push notification.

Concluding

This serverless microservice block can be integrated in a more complex design – repeating some of the considerations to that end – consider utilizing environment variables passed in as the template parameters for your stack. Consider designing the Lambda to be used with multiple apps and consider incorporating a Dynamodb data store to maintain a record of your notifications and statuses in case you need to resend.

Recent Posts

  • Coding a JSON format logger in Python for use as a Lambda Layer package
  • Configuring an S3 Bucket to send events to a Lambda destination for processing
  • How to request a public SSL certificate for a domain name from the AWS Certificate Manager Console
  • Creating automated CloudFormation Stack Build and Deployments with AWS CodePipeline and CodeBuild
  • A concise guide to setting up the AWS command-line libraries on your local development environment
  • How to implement a Lambda Authorizer for an AWS AppSync API and invoke the API with the required Authorization Token
  • Filtering CloudWatch Logs by LogGroups and LogStreams and reading them using Python and the Boto3 SDK
  • Azure AD Multi Tenancy issue in AWS Cognito
  • Setting up Enterprise Federation from Azure Active Directory to Amazon Cognito using Open ID Connect
  • How to Setup IAM Multifactor Authentication (MFA) for the AWS CLI

Categories

  • Amplify
  • API Gateway
  • AppSync
  • AWS CLI
  • CloudFormation
  • CloudWatch
  • Cognito
  • DynamoDB
  • EventBridge
  • KMS
  • Lambda
  • Projects
  • Route 53
  • SES
  • SNS

Post Tags

ACM Amplify API Gateway AppSync AWS CLI Azure Boto3 CloudFormation CloudWatch CodeBuild CodePipeline Cognito DynamoDB EventBridge Firebase IAM KMS Lambda OIDC Project Python Rekognition Route53 S3 SAM SES SNS VPC

©2022 The Lambda Blog