Control access to API

In this section we will be building API Access Control with Amazon Cognito. This will extend our architecture to ensure that only identified users are permitted access to the API.

5.1. Identify the risk of vulnerabilities.

Even though we have controlled traffic at multiple layers, anyone who knows your CloudFront Domain Name can access your API. Furthermore we do not know who accessed your API, so the owner of the traffic remains anonymous. Ideally we should ensure that only legitimate users who we are aware of are permitted access. This will mean that a successful API call will have to be both identified as well as authorized.

In this lab we will build out our architecture using Amazon Cognito. This addition will allow a user to sign in to a user pool which we create, obtain an identity or access token and then call the API method with one of the tokens. These tokens are typically set to the request’s Authorization header.

5.2. Sign up with Amazon Cognito user pools.

The second CloudFormation template which you have already deployed already contains an Amazon Cognito User Pool. We will start by obtaining the App client secret of Cognito, which we will use to generate an ID token at later points in the lab.

Click here for for SignUp instructions for Amazon Cognito

Take note of App client secret. Other required values such as user pool ID and App client ID are available in the Output section of the current cloudformation stack. Record these before moving to the next step.

5.3. Create Cognito user pools as Authorizer in API Gateway Console.

Amazon Cognito user pools are used to control who can invoke REST API methods. We now need to integrate the API with the Amazon Cognito user pool.

  1. Go to API Gateway in the AWS console and select API called wa-lab-rds-api. Section5 API without Authorizer

  2. From the main navigation pane, choose Authorizers and click Create New Authorizer button.

  • Type an authorizer name in Name.
  • Select Cognito as Authorizer Type.
  • Select your Cognito user pool (this should start with WAUserPool).
  • For Token source, type Authorization as the header name to pass the identity or access token.

Your configuration should be similar to the screenshot below:

Section5 Create New Authorizer

  • When you have completed the configuration, click on Create.
  1. You have now successfully added an Authorizer:

Section5 Output WAF

  1. From the main navigation pane, choose Resource to configure a COGNITO_USER_POOLS authorizer on methods.

Before you click Method Request, ensure that you refresh your browser. If you do not do this, our new Authorizer will not appear when trying to associate with Method Request.

Select Method Request as shown:

Section5 Method Request

  1. Choose the pencil icon next to Authorization. You should be able to see the Authorizer we created in the drop-down list.
  • To save the settings, choose the check mark icon Section5 Select Authorizer
  1. Since we made a change, we need to re-deploy the API. Complete the following steps:
  • Choose Action.
  • Deploy API. Section5 Deploy API
  1. Select Development stage as Dev from the drop-down list. Click Deploy. Section5 Select Stage

  2. Your API is now using COGNITO_USER_POOLS as Authorizer. Only users registered in COGNITO_USER_POOLS can access your API. Section5 Authorizer Association

5.4. Add Authorization header in CloudFront.

By default, CloudFront doesn’t consider headers when caching your objects in edge locations. Now your request must have an Authorization header with a valid ID Token to access API. Therefore, we need to configure CloudFront to forward headers to the API Gateway. Further details on this can be found here

  1. Go to CloudFront in the AWS console and select your CloudFront distribution.
  • From within the distribution, select the Behaviors tab.
  • Select Cache Behavior associated with our API Gateway using the tick box.
  • Click Edit.

Section5 Forward Header

  1. Select Authorization from the list of available headers and choose Add. To forward a custom header, enter the name of the header in the field, and choose Add Custom. Click Yes,Edit. Section5 Whitelist Headers

If you test out without Authorization header now, you will still see data being returned as it’s served from CloudFront edge caches. Let’s invalidate files to prevent this from happening.

  1. Invalidate files from CloudFront edge.
  • Select Invalidation tab.
  • Select Create Invalidation
  • Type /* , then click Invalidate button. Section5 Whitelist Headers

5.5. Generate an ID Token and send a request with ID Token.

After successful completing authentication, Amazon Cognito returns user pool tokens to your app. You can use these tokens to grant your users access to the API Gateway. Amazon Cognito user pools implements ID, access, and refresh tokens as defined by the OpenID Connect (OIDC) open standard.

In this lab, we will use an ID Token that is a JSON Web Token (JWT) that contains claims about the identity of the authenticated user such as name, email, and phone_number.

  1. In Cloud9, we will test with both CloudFrontEndpoint and APIGatewayURL to see the difference.
  • Execute the script called with the argument of your CloudFrontEndpoint.
python 'CloudFrontEndpoint'

You will get “Unauthorized” response with 401 response code.

Section5 Test API Cloud9

You must send Authorization header with valid ID token to access API now.

  1. Let’s generate an ID token with your username and password, Cognito user pool ID, App client ID, and App secret. We took note of App client secret when we signed up with Cognito. Other required values such as user pool ID, App client ID are available in Output section of the current cloudformation stack
 python <username> <user_password> <user_pool_id> <app_client_id> <app_client_secret>

You should be able to generate ID Token successfully. This will be valid for 60 minutes. Section5 Generate cognito ID Token

  1. Copy your ID Token you generate above. Send a request with this valid ID Token.
python 'CloudFrontEndpoint' ID_Token

You should be seeing your data as expected with a 200 response code. Now you must have provided an ID Token as the Authorization header to access your API only through CloudFront.

Section5 Send Request With Cognito ID Token

Ensure that you complete the tear down instructions in the final section to remove resources created in this lab.