AWS API gateway JWT Authorizer with Zitadel
Tags: aws, pulumi, jwt, authorizer
Published: 2023-02-26 18:12:50

**AWS API gateway** introduced HTTP API endpoints based integration in recent 2-3 years and they are different from the legacy REST API endpoint.

With this AWS also introduced JWT authorizer based authorization for the endpoints and made life easy for all the architects and developers, who were previously forced to use a custom authorizer only.

In this blog post which you are reading the primary focus is on **AWS API gateway JWT Authorizer** - with Pulumi as IAC provisioner & Zitadel for the identity/ authentication provider.

Reference to the zitadel setup for client_credentials flow [here](https://dev.to/karanbir/using-configuring-zitadel-for-integration-with-aws-4cgf)

## Prerequisites

- AWS account.
- Average knowledge about AWS, AWS API Gateway, AWS Lambda Functions.
- AWS CLI, Pulumi CLI on local machine.
- NodeJS 16 on local machine.
- Zitadel cloud account(setting up zitacloud is out of scope of this blog post) - refer my other blog post [here](https://dev.to/karanbir/using-configuring-zitadel-for-integration-with-aws-4cgf) for setting up zitadel cloud account
- You may also use any other Identity provider. (like AWS cognito, etc.)
- Great to have knowledge of JWT.

## Flow Diagram Positive Scenario

![Flow Diagram Positive Scenario Gif](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/7l1j6n7lhewjwfxwrjlo.gif)

0.  client fetches the access token required by the API endpoint before hitting the actual endpoint.
1. client sends request along with JWT as part of an **Authorization** Header prefixed with Bearer or can be without Bearer, to API gateway.
2. AWS API gateway delegates the Authorization to it's self managed Authorizer(not sure how they might be doing it - could be internally lambda managed?!).
3. fetches the jwks based on the issuer property & validates the signature of the JWT based on the kid in the input JWT.
4. internal JWT authorizer will return back true/ success.
5. API gateway will pass on the original request to the AWS lambda function.
6. Lambda function will reply back the response.
7. Response received from the lambda function is sent back to the client.

![Flow Diagram Positive Scenario](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/en5yobnxc3ywb5klzty7.png)

## Flow Diagram Negative Scenario


![Flow Diagram Negative Scenario GIF](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/y6mi9diyupeh4fwyuzlt.gif)

0. client fetches the access token required by the API endpoint before hitting the actual endpoint. (or if skipped for testing purpose)
1. client sends incorrect or blank or expired or misconfigured token.
2. AWS API gateway delegates the Authorization to it's self managed Authorizer(not sure how they might be doing it - could be internally lambda managed?!). It will delegate only if the header was present.
3. fetches the jwks based on the issuer property & validates the signature of the JWT based on the kid in the input JWT.
4. authorizer will reply back with false.
5. API gateway sends back the response as 401 (Unauthorized) or 403(forbidden).


![Flow Diagram Negative Scenario](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/01t538mxn8fgmli2rf8v.png)



## Code and configuration

The code repository referred is from the previous [blog post](https://dev.to/aws-builders/aws-api-gateway-mtls-authentication-with-smallstep-pulumi-2o65)

- change the configuration in the stack's yml files
- domain, cert, zitacloud issuer, etc. as per your setup

Link to the repo is [here](https://github.com/krnbr/aws-api-gateway/tree/authorizer) and the branch is [authorizer](https://github.com/krnbr/aws-api-gateway/tree/authorizer)

The config related to the JWT authorizer are in the [file](https://github.com/krnbr/aws-api-gateway/blob/authorizer/non-mtls-apis/Pulumi.neuw-ap-south-1.yaml):-

```
config:
  aws:profile: <AWS_PROFILE>
  aws:region: <AWS_REGION>
  non-mtls-apis:API_DOMAIN: <API_DOMAIN>
  non-mtls-apis:API_DOMAIN_MTLS: <MTLS_API_DOMAIN>
  non-mtls-apis:HOSTED_ZONE_NAME: <HOSTED_ZONE>
  non-mtls-apis:JWT:
    audiences:
      - test
      - aws_client
    issuer: https://instance_code.zitadel.cloud/
  non-mtls-apis:SUB_DOMAIN: <SUB_DOMAIN>
  non-mtls-apis:SUB_DOMAIN_MTLS: mtls.<SUB_DOMAIN>
```

Make changes to the audiences and issuer as per the setup.

- **audiences** will be part of the JWT access token as **aud** claim.
- **issuer** is also part of the JWT as **iss** claim.

If these configurations are not correct - then the API gateway will give error while accessing the endpoints

The error could be **401 unauthorized** and relating to the below:-

- issuer incorrect
- jwks url not accessible
- keys not resolvable, kid mismatch
- JWT's - exp nbf, iat not correct

---

Please feel free to reach me over Linkedin [here](https://www.linkedin.com/in/krnbr/) for further questions, doubts or suggestions.