AWS AppSync is Amazon Web Service’s excellent serverless managed GraphQL offering. It is a standout service that can be used to seamlessly implement scalable and performant fully serverless applications quickly thanks to its powerful managed resolvers that can go against a variety of data sources like DynamoDB and allows us to service any general client side requirement to retrieve or write data.
See this example linked if you are interested in a detailed end to end example of building a fully serverless application with AppSync.
If you are building a client side application, authorizing access to your backend APIs are probably one of the chief concerns and AppSync has a variety of options for you to do so. Using Cognito is an option and AppSync does integrate easily with that so that only authenticated users may invoke your API – but it is not required to use Cognito. Perhaps the most flexible and straightforward way to authorize calls to your AppSync API is to build a Lambda based Authorizer function which your AppSync API can be integrated with.
What are AppSync Lambda Authorizers and why use them?
A Lambda Authorizer is really just a humble Lambda function which can run any application code without the hassle or overhead of us personally managing it on a server – hence they are the key building blocks of serverless applications. The purpose of the AppSync Lambda authorizer though is to authorize invocations to an AppSync API.
The rules to authorize the incoming request to the API is fully flexible and entirely up to us – we can have it as simple as simply checking for the existence of a matching token from the client side, or build something more complex with role based authorization logic custom to the application – entirely up to us.
Once the Lambda is integrated with an AppSync API, it will provide the Lambda with an authorization token supplied to it in the incoming request and it only needs a boolean authorized or not response in return, but also allows us to set details like the ttl on the authorization and deny specific fields – more on this shortly.
return {
"isAuthorized": True,
"deniedFields": [],
"ttlOverride": 0
}
As to why it makes to sense to use them…it depends on your use case, but there are few specific paths in your decision tree. Lets consider them.
If your API end point simply users to be authenticated (as opposed to authorized) – your should go with a Cognito or Open ID Connect based authorization.
If you need custom role based authorization checks whether or not your users need to be authenticated, Lambda Authorizers are the way to go.
If you want a simple token based authorization check…or no authorization checks…you are better of picking Lambda authorizers for both. AppSync does not allow fully open invocations. At a minimum you will have to pick API_KEY based authorization – which from an implementation and invocation standpoint is the same as a Lambda Authorizer with a required token being sent by the invoker.
While you could use API Keys, keep in mind – they expire after a maximum of 365 days and will need to be renewed – you will need to manage that process with AppSync. With Lambda authorizer you have some flexibility in managing the tokens as it suits your own application process…and keeps the flexibility of expanding or changing the process in the future in a more managed way.
Coding a simple Lambda Authorizer to do a Token Match
Now lets first code a simple Lambda authorizer and then walk through the integration process next.
The Lambda code below is in Python – however the principle is the same depending on the AWS SDK of your choice – accept the code from the Lambda event that AppSync will supply your function after we have integrated it, run a simple equality check against the code you are expecting, return an authorization response back to AppSync.
import os
authorization_token = os.environ['AUTHORIZATION_TOKEN']
def lambda_authorizer(event, context):
#Simple string based token - but can be used with OAuth/OIDC based JSON Web Tokens and full on
#authentication of identity for role based checks
incoming_token = event["authorizationToken"]
#The full incoming request can be used for more complex validations if you need
#This example does not use this or other custom headers that may be passed
appsync_query_string = request_context["queryString"]
if incoming_token == authorization_token:
authorized = True
else:
authorized = False
return {
"isAuthorized": authorized,
"deniedFields": [],
"ttlOverride": 0
}
That is it really, but of course as I mentioned – this can be used for more complex operations – as I have highlighted where in the comments in the example above.
Next we will need to integrate an AppSync API with this Lambda Authorizer.
If you did not build this Lambda in the AWS console, it will need to either be packaged and deployed before it can be integrated with an AppSync API in the console. My preferred way is to combine it with the same Cloudformation stack as where your GraphQL API is and deploy everything together.
I will demonstrate both options – first the console way – scroll to the section after to see how to do this all seamlessly with Cloudformation.
Integration the Authorizer to an AppSync API via the console
Navigate to the AppSync API in the AppSync console and select Settings

Under the Default authorization mode tab, select AWS Lambda and then select your Lambda function from the drop down.
That is it. We will test this out shortly – but first as promised – wiring this up using Cloudformation.
Integration the Lambda Authorizer with an AppSync Cloudformation Stack
I generally prefer using Cloudformation Stacks because I find it a very good practice to attempt to adhere to provisioning Infrastructure As Code as far as possible. This is especially important for serverless applications – it will get very tedious if you need to manually replicate your AWS stacks across regions or accounts – a common use when moving from development to higher environments.
See some of my linked examples above for full and detailed AppSync Cloudformation templates including GraphQL schema, but for this article – I am only linking the relevant snippets to integrate the API with the Authorizer.
First – the Lambda Authorizer definition itself in yaml
AppSyncAuthorizer:
Type: AWS::Serverless::Function
Properties:
CodeUri: ./appsync-authorizer/
Handler: appsync-authorizer.lambda_authorizer
Description: Lambda Authorizer for AppSync
FunctionName: appsync-authorizer
Environment:
Variables:
AUTHORIZATION_TOKEN: TOKEN123
Next, we need to define the AppSync API, set it to use AWS_LAMBDA as the authorizer and also give AppSync IAM permissions to allow it to invoke the Lambda authorizer.
AppSyncRole:
Type: "AWS::IAM::Role"
Properties:
AssumeRolePolicyDocument:
Version: 2012-10-17
Statement:
- Effect: "Allow"
Principal:
Service:
- "appsync.amazonaws.com"
Action:
- "sts:AssumeRole"
Path: "/"
AppSync:
Type: "AWS::AppSync::GraphQLApi"
Properties:
Name: "sample-appsync-api"
AuthenticationType: "AWS_LAMBDA"
LambdaAuthorizerConfig:
AuthorizerResultTtlInSeconds: 0
AuthorizerUri: !GetAtt AppSyncAuthorizer.Arn
AppsyncPermission:
Type: AWS::Lambda::Permission
Properties:
FunctionName: !GetAtt AppSyncAuthorizer.Arn
Action: lambda:InvokeFunction
Principal: appsync.amazonaws.com
SourceAccount: !Ref 'AWS::AccountId'
SourceArn: !GetAtt AppSync.Arn
The rest of the template will be whatever else your AppSync API needs – schema, data sources, resolvers for the most part.
Deploy the template and lets see how to test the API.
Testing the Lambda Authorizer with by invoking the API from the client side
The most straightforward way is to use the AppSync console directly where it will be expecting you to add your token

Or pass the token using curl
$ curl -XPOST -H "Content-Type:application/graphql" -H "Authorization:TOKEN123" -d '{ "query":
"your_appsync_query { query_name { field_name } }" }' https://your_appsync_query/graphql
Or for actual client side development, I prefer to use the Amplify JavaScript library
...
...
import Amplify, { API } from 'aws-amplify';
import * as mutations from './graphql/mutations';
...
...
...
const config = {
aws_appsync_graphqlEndpoint:
'https://your_appsync_query/graphql',
aws_appsync_region: 'your_region',
aws_appsync_authenticationType: 'AWS_LAMBDA',
};
Amplify.configure(config);
...
...
...
const submitData = () => {
API.graphql({
query: mutations.sendData,
variables: { field1: data1, field2: data2 },
authToken: 'TOKEN123',
});
};
This should hopefully be enough to get you using Lambda authorizers for your own AppSync applications should you need its flexibility.