AWS Security Blog
How to secure API Gateway HTTP endpoints with JWT authorizer
This blog post demonstrates how you can secure Amazon API Gateway HTTP endpoints with JSON web token (JWT) authorizers. Amazon API Gateway helps developers create, publish, and maintain secure APIs at any scale, helping manage thousands of API calls. There are no minimum fees, and you only pay for the API calls you receive.
Based on customer feedback and lessons learned from building the REST and WebSocket APIs, AWS launched HTTP APIs for Amazon API Gateway, a service built to be fast, low cost, and simple to use. HTTP APIs offer a solution for building APIs, as well as multiple mechanisms for controlling and managing access through AWS Identity and Access Management (IAM) authorizers, AWS Lambda authorizers, and JWT authorizers.
This post includes step-by-step guidance for setting up JWT authorizers using Amazon Cognito as the identity provider, configuring HTTP APIs to use JWT authorizers, and examples to test the entire setup. If you want to protect HTTP APIs using Lambda and IAM authorizers, you can refer to Introducing IAM and Lambda authorizers for Amazon API Gateway HTTP APIs.
Prerequisites
Before you can set up a JWT authorizer using Cognito, you first need to create three Lambda functions. You should create each Lambda function using the following configuration settings, permissions, and code:
- The first Lambda function (Pre-tokenAuthLambda) is invoked before the token generation, allowing you to customize the claims in the identity token.
- The second Lambda function (LambdaForAdminUser) acts as the HTTP API Gateway integration target for /AdminUser HTTP API resource route.
- The third Lambda function (LambdaForRegularUser) acts as the HTTP API Gateway integration target for /RegularUser HTTP API resource route.
IAM policy for Lambda function
You first need to create an IAM role using the following IAM policy for each of the three Lambda functions:
Settings for the required Lambda functions
For the three Lambda functions, use these settings:
Function name | Enter an appropriate name for the Lambda function, for example:
|
Runtime | Choose Node.js 12.x |
Permissions | Choose Use an existing role and select the role you created with the IAM policy in the Prerequisites section above. |
Pre-tokenAuthLambda code
This first Lambda code, Pre-tokenAuthLambda, converts the authenticated user’s Cognito group details to be returned as the scope claim in the id_token returned by Cognito.
LambdaForAdminUser code
This Lambda code, LambdaForAdminUser, acts as the HTTP API Gateway integration target and sends back the response Hello from Admin User when the /AdminUser resource path is invoked in API Gateway.
LambdaForRegularUser code
This Lambda code, LambdaForRegularUser , acts as the HTTP API Gateway integration target and sends back the response Hello from Regular User when the /RegularUser resource path is invoked within API Gateway.
Deploy the solution
To secure the API Gateway resources with JWT authorizer, complete the following steps:
- Create an Amazon Cognito User Pool with an app client that acts as the JWT authorizer
- Create API Gateway resources and secure them using the JWT authorizer based on the configured Amazon Cognito User Pool and app client settings.
The procedures below will walk you through the step-by-step configuration.
Set up JWT authorizer using Amazon Cognito
The first step to set up the JWT authorizer is to create an Amazon Cognito user pool.
To create an Amazon Cognito user pool
- Go to the Amazon Cognito console.
- Choose Manage User Pools, then choose Create a user pool.
- Enter a Pool name, then choose Review defaults.
- Choose Add app client.
- Enter an app client name. For this example, keep the default options. Choose Create app client to finish.
- Choose Return to pool details, and then choose Create pool.
To configure Cognito user pool settings
Now you can configure app client settings:
- On the left pane, choose App client settings. In Enabled Identity Providers, select the identity providers you want for the apps you configured in the App Clients tab.
- Enter the Callback URLs you want, separated by commas. These URLs apply to all selected identity providers.
- Under OAuth 2.0, select the from the following options.
- For Allowed OAuth Flows, select Authorization code grant.
- For Allowed OAuth Scopes, select phone, email, openID, and profile.
- Choose Save changes.
- Now add the domain prefix to use for the sign-in pages hosted by Amazon Cognito. On the left pane, choose Domain name and enter the appropriate domain prefix, then Save changes.
- Next, create the pre-token generation trigger. On the left pane, choose Triggers and under Pre Token Generation, select the Pre-tokenAuthLambda Lambda function you created in the Prerequisites procedure above, then choose Save changes.
- Finally, create two Cognito groups named admin and regular. Create two Cognito users named adminuser and regularuser. Assign adminuser to both admin and regular group. Assign regularuser to regular group.
Configuring HTTP endpoints with JWT authorizer
The first step to configure HTTP endpoints is to create the API in the API Gateway management console.
To create the API
- Go to the API Gateway management console and choose Create API.
- Choose HTTP API and select Build.
- Under Create and configure integrations, enter JWTAuth for the API name and choose Review and Create.
- Once you’ve created the API JWTAuth, choose Routes on the left pane.
- Choose Create a route and select GET method. Then, enter /AdminUser for the path.
- Repeat step 5 and create a second route using the GET method and /RegularUser for the path.
To create API integrations
- Now that the two routes are created, select Integrations from the left pane.
- Select GET for the /AdminUser resource path, and choose Create and attach an integration.
- To create an integration, select the following values
Integration type: Lambda function
Integration target: LambdaForAdminUser - Choose Create.
NOTE: LambdaForAdminUser is the Lambda function you previously created as part of the Prerequisites procedure LambdaForAdminUser code. - Next, select GET for the /RegularUser resource path and choose Create and attach an integration.
- To create an integration, select the following values
Integration type: Lambda function
Integration target: LambdaForRegularUser - Choose Create.
NOTE: LambdaForRegularUser is the Lambda function you previously created as part of the Prerequisites procedure LambdaForRegularUser code.
To configure API authorization
- Select Authorization from the left pane, select /AdminUser path and choose Create and attach an authorizer.
- For Authorizer type select JWT and under Authorizer settings enter the following details:
Name: JWTAuth Identity source: $request.header.Authorization Issuer URL: https://cognito-idp.us-east-1.amazonaws.com/<your_userpool_id> Audience: <app_client_id_of_userpool> - Choose Create.
- In the Authorizer for route GET /AdminUser screen, choose Add scope in the Authorization Scope section and enter scope name as admin-<app_client_id> and choose Save.
- Now select the /RegularUser path and from the dropdown, select the JWTAuth authorizer you created in step 3. Choose Attach authorizer.
- Choose Add scope and enter the scope name as regular-<app_client_id> and choose Save.
- Enter Test as the Name and then choose Create.
- Under Select a stage, enter Test, and then choose Deploy to stage.
Test the JWT authorizer
You can use the following examples to test the API authentication. We use Curl in this example, but you can use any HTTP client.
To test the API authentication
- Send a GET request to the /RegularUser HTTP API resource without specifying any authorization header.
API Gateway returns a 401 Unauthorized response, as expected.
{“message”:”Unauthorized”}
- The required $request.header.Authorization identity source is not provided, so the JWT authorizer is not called. Supply a valid Authorization header key and value. You authenticate as the regularuser, using the aws cognito-idp initiate-auth AWS CLI command.
CLI Command response:
The command response contains a JWT (IdToken) that contains information about the authenticated user. This information can be used as the Authorization header value.
- API Gateway returns the response Hello from Regular User. Now test access for the /AdminUser HTTP API resource with the JWT token for the regularuser.
API Gateway returns a 403 – Forbidden response.
{“message”:”Forbidden”}
The JWT token for the regularuser does not have the authorization scope defined for the /AdminUser resource, so API Gateway returns a 403 – Forbidden response. - Next, log in as adminuser and validate that you can successfully access both /RegularUser and /AdminUser resource. You use the cognito-idp initiate-auth AWS CLI command.
- Using Curl, you can validate that the adminuser JWT token now has access to both the /RegularUser resource and the /AdminUser resource. This is possible when adminuser is part of both Cognito groups, so the JWT token contains both authorization scopes.
API Gateway returns the response Hello from Regular User
API Gateway returns the following response Hello from Admin User
CLI Command response:
Conclusion
AWS enabled the ability to manage access to an HTTP API in API Gateway in multiple ways: with Lambda authorizers, IAM roles and policies, and JWT authorizers. This post demonstrated how you can secure API Gateway HTTP API endpoints with JWT authorizers. We configured a JWT authorizer using Amazon Cognito as the identity provider (IdP). You can achieve the same results with any IdP that supports OAuth 2.0 standards. API Gateway validates the JWT that the client submits with API requests. API Gateway allows or denies requests based on token validation along with the scope of the token. You can configure distinct authorizers for each route of an API, or use the same authorizer for multiple routes.
To learn more, we recommend:
- Evaluating access control methods to secure Amazon API Gateway APIs
- Building faster, lower cost, better APIs – HTTP APIs now generally available
- Building fine-grained authorization using Amazon Cognito, API Gateway, and IAM
- Control access to your APIs using Amazon API Gateway resource policies
If you have feedback about this post, submit comments in the Comments section below. If you have questions about this post, contact AWS Support.
Want more AWS Security news? Follow us on Twitter.