Operating with AppSync from AWS Lambda
I wasn’t always sure about AWS Lambda as the best option to provide the full back-end of a medium-large app. Nevertheless, my opinion has recently changed (probably thanks to the enthusiasm of my colleague Luke and the discovery of the framework Serverless) and while I won't go through the advantages of using a serverless architecture in this article, I will admit I’ve become a true believer in its potential and I'm convinced it will be part of the architecture solution for most of the apps in the future.
For our latest hackathon adventure, the team opted for a serverless back-end composed by an AppSync layer which would work as a gateway to our services, complemented with AWS Lambda functions for specific tasks. If you are interested in the front-end side, please read (and clap) James’s amazing article to find out how he got AWS AppSync, React Native and React Apollo playing nicely all together.
Using AppSync from our Lambda functions
Placing ourselves in the back-end side, one of the tasks approached by Lambda aimed to retrieve Cafe products from our iZettle account and import them into the app database. The logic needed to get some information (e.g. does the product already exist?) from AppSync (using a GraphQL query) to subsequently persist it with a mutation.
This article written by Adrian Hall explains extremely well how to trigger an AppSync operation (a mutation) from AWS Lambda and it shows how powerful this approach is since you'll be able to notify subscribed clients in real time. That's something we wanted (it's pretty cool allowing users to order a recently added new type of coffee, isn't it?), however, in his example, he is based in the use of IAM roles as the authentication method in AppSync. Due to our requirements, we decided to go for Cognito user pool to authenticate calls to AppSync because that would allow us to access to the user information in our resolvers, and control exactly the data allowed to be retrieved/updated once the user had been identified.
Create the Server App Client
For our example, we’ll assume the Cognito User Pool has already been created. So we’ll need to create a new App client for the pool making sure the option Enable sign-in API for server-based authentication (ADMIN_NO_SRP_AUTH) is checked. This authentication solution is designed to be used from server-side secure apps as an alternative of SRP (Secure Remote Password) to avoid some of the expensive calculations of this protocol, making use of AWS Credentials instead (you'll need an IAM role with the adequate access to Cognito User Pools to carry out admin authentication actions).
The client app can be created either via UI:
Or as part of the stack created and deployed with CloudFormation through the Serverless framework:
Get a JW Token to authenticate the Cognito user
Now, we'll be able to get JSON Web Tokens that will give access to the benefits of AppSync:
Note: for the given example, we assumed there is an existing user in the user pool that has been verified. In the next article, I'll explain how to automate its creation.
Operate with AppSync
To actually communicate our function with AppSync we made use of the package aws-appsync which works as a wrapper of Apollo and allows authentication through Cognito pools:
Once the AppSync Client is initialised, we can perform queries...
or, even better, the mutations we were looking for…
Any client subscribed to the data being mutated will be notified, keeping your users up to date with the latest changes.
In the next chapter, we’ll run through some of the things that can be improved:
- Automation: Creation of the resources needed for this solution with CloudFormation and Serverless framework.
- Performance: Reuse of access tokens across functions calls, speeding up the authentication process.