The aim of this workshop is, on one hand, show you how you can integrate the authentication in an API Gateway. On the other hand, we will explore different authorization mechanisms used by the API Gateway.

What you will learn

In this workshop you will learn:

Overall, you will learn how to create a secure and customizable API Gateway. Additionally, you will have experimented with multiple security options that API Gateway provide us and which are usually useful in many projects.

According to the AWS Documentation:

Amazon API Gateway is a fully managed service that makes it easy for developers to create, publish, maintain, monitor, and secure APIs at any scale. APIs act as the “front door” for applications to access data, business logic, or functionality from your backend services. Using API Gateway, you can create RESTful APIs and WebSocket APIs that enable real-time two-way communication applications. API Gateway supports containerized and serverless workloads, as well as web applications.

Features:

According to the AWS Documentation:

Amazon Cognito lets you add user sign-up, sign-in, and access control to your web and mobile apps quickly and easily. Amazon Cognito scales to millions of users and supports sign-in with social identity providers, such as Facebook, Google, and Amazon, and enterprise identity providers via SAML 2.0.

Features

Components

(for more details about these components, visit the AWS Documentation)

  1. User Pool:
    • Design sign-up and sign-in webpages for your app.
    • Access and manage user data.
    • Track user device, location, and IP address, and adapt to sign-in requests of different risk levels.
    • Use a custom authentication flow for your app.
  2. Federated Identity:
    • Give your users access to AWS resources, such as an Amazon Simple Storage Service (Amazon S3) bucket or an Amazon DynamoDB table.
    • Generate temporary AWS credentials for unauthenticated users.

First of all, we need to set up the environment to continue with this lab. We need to first clone the repository https://github.com/ronaldtf/aws-auth-apigateway

$> git clone https://github.com/ronaldtf/aws-auth-apigateway.git

The directory structure is as follows:

In order to set up the infrastructure, we can opt for one of these methods:

  1. Run the deployment script
  2. Launch the code from the AWS Console

Case 1: Run the deployment script

Requirements

Before running the script, we need to verify that we have our environment ready to launch it. You should check that you have installed and configured the following tools:

AWS Command Line Interface:: AWS CLI is a tool that let us send requests to AWS API to perform certain actions. Regarding the operating system you use, you can either download the installer and install it or use the pip installer. To get details instructions of how to do this follow the AWS Command Line Interface page. For instance, for Unix OS, you need Python3 and pip to be installed. Then, execute:

$ pip install awscli
$ pip install aws-mfa

We need to set up our environment to later be able to deploy our resources. To do so, we must follow the AWS documentation. We describe below the procedure anyway.

In the IAM Section in the AWS Console, we have to go to users and select the user we want to use for the deployment. We select Security credentials and Create access key (if not previously created). Copy the user access key and secret access key provided.

If you do not find the file ~/.aws/credentials in the cases below, type:

$ aws configure

and set the default region (e.g. eu-west-1).

Case 1: Unique account for users and services

If you are not using MFA and simply use an account for users and services (which is not recommended), just set the values copied above in an ~/.aws/credentials file:

    [default]
    aws_access_key_id = YOURACCESSKEYID
    aws_secret_access_key = YOURSECRETACCESSKEY

Case 2: AWS Users Account and AWS Services Account separately

If you use MFA and a user account for the IAM users and a service account for the services (and where you want to deploy your services) as shown in the image below…

… you must follow this configuration:

$ pip install aws-mfa
[profile default]
...

[profile lab-long-term]
region = eu-west-1
output = json
role_arn = arn:aws:iam::123456789012:role/role_to_be_assumed
source_profile = default

NOTE: the source_profile is the profile that gives us permissions to do an assume role. Therefore, we need to define those credentials for it in the ~/.aws/config file.

[lab-long-term]
aws_access_key_id = YOURACCESSKEYID
aws_secret_access_key = YOURSECRETACCESSKEY
aws_mfa_device = arn:aws:iam::123456789012:mfa/iam_user
aws-mfa --profile lab

This will place the right credentials in the ~/.aws/credentials file. However, note that this credentials will expire and we will need to execute the command below again once they are expired.

Set up

Before running the script, we need to edit it and set the following parameters:

The, we simply run the script:

$> ./deploy.sh

Case 2: Deploy it from the console

  1. Create a bucket and place the python.zip file in that bucket

  2. Go to the CloudFormation service, and deploy a stack by selecting the deploy.yaml file placed in the deployment directory. Pass the name of the created bucket as a parameter

  3. Once done, you have to get the output of the Stack and fill in the values of the variables in web/js/config.js

  4. Upload the test.json file to the S3 bucket indicated in the output (key: ReferredBucket.

Post set-up

In order to do the test, you need to create a user in Cognito

NOTE: User name must be an email address!

In order to test this example, we will use 2 methods:

  1. Using the example page
  2. Using the curl command (by adding the Authorization header to your request)

The procedure of how to perform this will be explained during the workshop

In this case, we will test the example by using the example page (doing it with the curl command is possible, but complex).

Following the Part 1, will you be able to configure this case?

API keys are alphanumeric string values that you distribute to application developer customers to grant access to your API. You can use API keys together with usage plans or Lambda authorizers to control access to your APIs. API Gateway can generate API keys on your behalf, or you can import them from a CSV file.

In order to test this example, we will use 2 methods:

  1. Using the example page (NOTE: you need to adjust some settings)
  2. Using the curl command (by adding the X-API-Key header to your request)

To implement this, you need:

To test this, use a new API Gateway resource and method. You can reuse the default public lambda as the backend for this case.

NOTE: Bear in mind that, after you have changed the created method by using the API key, you need to redeploy your API Gateway

For generating a custom token, visit JWT IO page

Do you know how to customize your current authorizer to validate your custom token (instead of the one provided by Cognito)?

NOTE: There is already a lambda implemented to validate the custom token (named <stack_name>-authorizer). This authorizer only accepts HS256 encoded tokens (bear that in mind, otherwise it would not work)

IMPORTANT: If you are going to use Cognito tokens, you must:

  • Change the token type to HS256 (the implemented custom authorizer only support this encryption type)
  • Remove the aud field (otherwise, we will get an error Invalid audience)

For this case, we will only use the curl command to test it. Remember to use Authorization header to add the token in the authorizer (otherwise, it will not work)

Extracted from AWS Documentation

API Gateway resource policy

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:region:account-id:api-id/",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": ["192.0.2.0/24", "198.51.100.0/24" ]
                }
            }
        }
    ]
}

API Gateway resource policy with IAM

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "",
            "Action": "execute-api:Invoke",
            "Resource": [
                "arn:aws:execute-api:region:account-id:api-id/"
            ],
            "Condition" : {
                "StringEquals": {
                    "aws:SourceVpc": "vpc-2f09a348"
                    }
            }
        }
    ]
}

API Gateway resource policy with Cognito

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": "arn:aws:execute-api:region:account-id:api-id/",
            "Condition": {
                "IpAddress": {
                    "aws:SourceIp": ["192.0.2.0/24", "198.51.100.0/24" ]
                }
            }
        }
    ]
}

API Gateway resource policy with lambda authorizer

{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Deny",
            "Principal": "*",
            "Action": "execute-api:Invoke",
            "Resource": [
                "arn:aws:execute-api:region:account-id:api-id/"
            ],
            "Condition" : {
                "StringNotEquals": {
                    "aws:SourceVpce": "vpce-1a2b3c4d"
                }
            }
        }
    ]
}

This lab goes beyond the purpose of the workshop. However, I have found interesting to include a section here.

This is the procedure:

  1. Create a private API Gateway and a mock resource

  2. Create an interface endpoint (execute-api) to the API Gateway to be used within a VPC

  3. To grant access to your VPC endpoint, create a resource policy and attach it to your API

  4. From an EC2 instance from your VPC, call a method by using curl and the interface endpoint as an endpoint

Now that you know…

… it’s time to put your hands on new projects and start new challenges!