Knowledge Base Authorisation using Amazon API Gateway

Dan Cooper AWS

We take a tour of the authorisation methods that are available with Amazon API Gateway and try them out using Postman.

According to the marketing spiel, 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”.

API Gateway

Despite the 2015 launch, I only properly started to review its capabilities earlier this year. As per the guidance, the first thing I did was build the example Pet Store REST API. This creates a demo API with a couple of resources with GET methods to help you quickly get to grips with how it works.

More recently, I looked into authorisation methods and, as you would expect, found several options available. This article provides a run-down on these options and how to test them using Postman.

Usage plans and API keys

API Gateway provides usage plans and API keys to allow your customers to “access selected APIs at agreed-upon request rates and quotas that meet their business requirements and budget constraints”.

API keys can be associated with one or more usage plans, and usage plans can be associated with one or more deployed stages of your API (such as production, test and so on). The aforementioned request rates and quotas are attached to usage plans rather than individual API keys.

  • Limited to 500 API keys per region (but can you request an increase)
  • Ideal for controlling throughput, not authentication and authorisation
  • API keys must be passed in a header key called x-api-key

Postman1

Example: Add an API key requirement to an API resource method

  1. Go to the API Gateway console and select your existing API (e.g. PetStore).
  2. In the Resources pane, select the Method Request for the API resource method you wish to update.
  3. Set API Key Required to true.
  4. Deploy your API to a new or existing stage.
  5. In the Usage Plans pane, create a plan with your preferred throttling and quota values.
  6. Associate the usage plan with the stage you deployed above.
  7. In the API Keys pane, create an API key and associate it with the usage plan.
  8. Try a request to the API resource method using Postman. You should find your request is successful only when you include a valid API key in an x-api-key header key.

Postman1

IAM authorisation

You can use IAM authorisation with API Gateway to first authenticate and then authorise an IAM user that has permission to invoke your API.

Example: Add IAM authorisation to an API resource method

  1. Go to the API Gateway console and select your existing API (e.g. PetStore).
  2. In the Resources pane, select the Method Request for the API resource method you wish to update.
  3. Set Authorization to AWS_IAM.
  4. Deploy your API to a new or existing stage.
  5. In the IAM console, create a user that has permissions to invoke the API resource method that you updated above:
    {
     "Version": "2012-10-17",
     "Statement": [
             {
                     "Sid": "PetStoreGet",
                     "Effect": "Allow",
                     "Action": "execute-api:Invoke",
                     "Resource": "arn:aws:execute-api:{Region}:*:{API identifier}/demo/GET/pets"
             }
     ]
    }
  6. Try a request to the API resource method using Postman. Your request will need to include an AWS Signature that contains API region and the user’s access key and secret access key.

Postman1

Cognito authorisation

API Gateway allows you to connect with an existing Cognito user pool to control who has access to your API. With this approach, Cognito handles the user authentication and returns a token. That token is then presented within each request to your API and verified by a Cognito authoriser associated with your API.

  • Uses a Cognito user pool for user management and authentication
  • Cognito authoriser associated with your API handles authorisation

Example: Add a Cognito authoriser to an API resource method

  1. Go to the API Gateway console and select your existing API (e.g. PetStore).
  2. In the Authorizers pane, create a new authoriser:

    Name: MyCognitoAuth

    Type: Cognito

    Cognito User Pool: The region and name of your user pool

    Token Source: authorizationToken

  3. In the Resources pane, select the Method Request for the API resource method you wish to update.
  4. Set Authorization to use your new Cognito authoriser. You may need to refresh the page if it doesn’t appear in the list.
  5. Deploy your API to a new or existing stage.
  6. Try a request to the API resource method using Postman. The request must include a valid Cognito token in a header key called authorizationToken (or whatever you specified above). You can generate a token (called IdToken) by logging into your user pool or by running this AWS CLI command:

    aws cognito-idp initiate-auth --client-id {Client App ID associated with your User Pool} --auth-flow USER_PASSWORD_AUTH --auth-parameters USERNAME={Username},PASSWORD={Password}

Postman1

Postman1

Cognito authorisation with user pool groups

Cognito authorisers provide access to users in a specific user pool but they don’t provide finer-grained authorisation; the sort that grants access to users in a specific group within your user pool, like an admin group for instance.

To achieve this, you need to combine your Cognito authoriser with a Lambda proxy integration. This proxies requests through to Lambda and makes the request details available in the event of the handler function.

Within the function, you can ascertain the user’s group and use that to decide whether or not to provide access. Alternatively, you can ascertain the IAM role of the user’s group (which you can attach in Cognito) and then configure your API to assume that role.

  • Finer-grained authorisation using Cognito user pools and groups, and Lambda

  • Use custom code within a Lambda function to control access or assume IAM roles

Example: Use Lambda to authorise a user in specific Cognito user pool groups

  1. Go to the Lambda console and create a Python function. The function below is designed to return a 401 if the user is not in a group called admins.

    import boto3
    def lambda_handler(event, context):
    
    groups = event['requestContext']['authorizer']['claims']['cognito:groups']
    
    if "admins" in groups:
        # Do stuff
        return { "statusCode": 200, "headers": { }, "body": "Welcome, admin" }
    else:
        # Not authorised
        return { "statusCode": 401, "headers": { }, "body": "Unauthorized" }
    
  2. Go to the API Gateway console and select your existing API (e.g. PetStore).
  3. In the Authorizers pane, create a new authoriser:

    Name: MyCognitoAuth

    Type: Cognito

    Cognito User Pool: The region and name of your user pool

    Token Source: authorizationToken

  4. In the Resources pane, create a new resource with a GET method:

    Integration type: Lambda function

    Use Lambda Proxy integration: Yes

    Lambda Function: The name of your new Lambda function

  5. Select the Method Request for the API resource method you just created.
  6. Set Authorization to use your new Cognito authoriser. You may need to refresh the page if it doesn’t immediately appear in the list.
  7. Deploy your API to a new or existing stage.
  8. Try a request to the API resource method using Postman. The request must include a valid Cognito token in a header key called authorizationToken (or whatever you specified above). You can generate a token by logging into your user pool or by running this AWS CLI command:

    aws cognito-idp initiate-auth --client-id {Client App ID associated with your User Pool} --auth-flow USER_PASSWORD_AUTH --auth-parameters USERNAME={Username},PASSWORD={Password}

Example: Use Lambda to assume the IAM role associated with a Cognito user pool group

  1. Go to the Lambda console and create a Python function. The function will try to assume the IAM role associated with the user’s Cognito user pool group. Note, the role needs the execute-api:Invoke permission and a trust policy to allow users in the account to assume it.

    import boto3
    def lambda_handler(event, context):
    
    role = event["requestContext"]["authorizer"]["claims"]["cognito:preferred_role"]
    client = boto3.client("sts")
    
    # Assume first role found
    response = client.assume_role(RoleArn=role, RoleSessionName="AssumedRole")
    
    output = { "statusCode": 200, "headers": { }, "body": "Group role has been assumed" }
    
    return output
    
  2. In the Cognito console, check you have associated an IAM role with the user pool group of your user.
  3. Follow the rest of the steps in the previous example.

Lambda authorisers

There is another option for when IAM and Cognito don’t fit your use case: Lambda authorisers. This type of authoriser enables you to control access using your own authentication and authorisation methods using Lambda.

  • Authenticate and authorise using Lambda and your own user database

  • Supports caching for improved performance

  • Needs to return an IAM policy document plus any custom key value pairs which may be useful downstream

Example: Create a Lambda authoriser using a Python blueprint

  1. Go to the Lambda console and create a Python function using the api-gateway-authorizer-python blueprint.

  2. Go to the API Gateway console and select your existing API (e.g. PetStore).

  3. In the Authorizers pane, create a new authoriser:

    Name: Lambda

    Lambda Function: Enter the name of your new Lambda function

    Token Source: authorizationToken (or whatever you specified in the Lambda function)

    Authorization Caching: Recommended but may wish to disable during this example

  4. In the Resources pane, select the Method Request for the API resource method you wish to update.

  5. Set Authorization to use your new Lambda authoriser.

    You may need to refresh the page if it doesn’t appear in the list.

  6. Deploy your API to a new or existing stage.

  7. Try a request to the API resource method using Postman. The request must include a dummy token in a header key called authorizationToken (or whatever you specified above).

Further options

Have you found any other ways of controlling access to your API in API Gateway? Get in touch and let me know.

Dan Cooper: Allies AWS Principal Consultant

Dan Cooper

CEO and Principal Consultant, Allies Computing Professional Services

Dan provides AWS consultancy to businesses, helping them migrate, transform and optimise their workloads using the AWS cloud. He is a Certified AWS Solution Architect and specialises in high availability architecture, ETL and VPC design.

Receive more great content just like this

Our email newsletter goes out once a month and we will only use your details to send you links to products and articles we think you might be interested in.

You may also like

Live Start Loading NowChatting Offline
Cookie

Cookie consent

We use some essential cookies to make this website work. We'd like to set additional cookies to help us measure your experience when you view and interact with the website.

Cookie policy