AWS API Gateway Custom Authorizer with C#

Charles Yang
4 min readSep 7, 2018

--

During the weekend, I was exploring the AWS API Gateway. The first thing I was trying to do was to create the typical “HELLO WORLD” example.

After creating my first “HELLO WORLD” API Gateway (the default PetStore API Gateway example provided by AWS), the “authorization” property quickly caught my attention.

Authorization property is shown as none.

I was thinking of some use cases. If I am going to use the API Gateway, I definitely need to look into the authorization to verify my JWT token.

After a few searches on Google, I found the GrandmaRecipes repository presented by the AWS team during the AWS Summit 2018 in Sydney. I was able to reuse the authorizer in the Github repository and configure it to my own needs by updating the Issuer, Audience and the SecretKey.

During the implementation, I have encountered some issues and would like to share my solution with people who might encounter the same issue as me.

1| How to hide the secret

I am using the variables MY_SECRET, AWS_ACCOUNT_ID and AWS_KMS_KEY in my lambda config.

the basic lambda configuration json

The environment-variables is used to pass our key-value pair variable.
The kms-key is used to pass the key I created from the AWS Key Management System to encrypt the secret.

I will replace them with the variables I set up in the Environment Variables provided by the bitbucket pipeline.

bitbucket environment variables

In the bitbucket-pipelines.yml, I am using the command sed to replace the variables I mentioned above in aws-lambda-tools-defaults.json.

the sed command on line 30

2| Removing the string Bearer while validating

In the authorizer from the GrandmaRecipes repository, we are using System.IdentityModel.Tokens.Jwt to validate the authorization token.

I kept getting error messages indicating that the JWT is not well formed. I was not able to figure out what was happening until I realized that the received token is

Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJVc2VySWRlbnRpZmllciI6Ij…

By removing the “Bearer” from the token, the code works as expected.

3| Handling 401 exception manually

In some cases, we might want to handle our own exception in the custom authorizer. We can throw the exception like the code below…

throw new Exception("Unauthorized"); // 401
throw new Exception(); // 500

For more details on the API Gateway response check out here.

4| The Response from API Gateway

This is the most tricky part. Most of my time was spent here because of my bad habit of not reading the documentation properly.

no pictures, no fun

The custom authorizer’s Lambda function returns an output that must include the principal identifier (principalId) and a policy document (policyDocument) containing a list of policy statements. The output can also include a context map containing key-value pairs.

I was trying to change the version date.

not working example, DO NOT COPY!

I was also trying to add more information to the contextOutput, such as user permissions.

not working example, DO NOT COPY!

I received the error message below when I tried to do the two changes above. The error message was not very intuitive but ultimately was being thrown because the contextOutput can only support key-value pairs, with the value of not supporting complex object types [e.g. arrays].

Authorizer result body before parsing: {...}
Mon Sep 03 07:08:31 UTC 2018 : Execution failed due to configuration error: Could not parse policy: {...}
Mon Sep 03 07:08:31 UTC 2018 : AuthorizerConfigurationException

By not updating the version date and changing the code to work with string-based key-values for the contextOutput HashSet property, we are able to add the information we need.

working example
working example

Test Results

results for testing the custom authorizer

--

--