fbpx

Protect public customers for Amazon Cognito through the use of an Amazon CloudFront proxy

In Amazon Cognito user pools , an app client can be an entity which has permission to call unauthenticated API operations (that’s, operations that don’t have an authenticated user), such as for example operations to join up, register, and handle forgotten passwords. In this article, I show you a remedy made to protect these API operations from unwanted bots and distributed denial of service (DDoS) attacks.

To safeguard Amazon Cognito customers and services, Amazon Cognito applies request rate quotas on all API categories, and throttles rapid calls that exceed the assigned quota. For that good reason, you must make sure your applications control who is able to call unauthenticated API operations and at what rate, in order that user calls aren’t throttled due to unwanted or misconfigured clients that call these API operations at high rates.

 

App clients belong to 1 of 2 categories: public clients (used from web or mobile applications) and private or confidential clients (used from the secured backend). Public clients shouldn’t have secrets, since it isn’t possible to safeguard secrets in these kinds of clients. Confidential clients, alternatively, work with a secret to authorize calls to unauthenticated operations. In these clients, the trick could be protected in the backend.

The advantage of utilizing a confidential app client with a secret in Amazon Cognito is that unauthenticated API operations encourage only the calls offering the secret hash because of this client, and can drop calls having an missing or invalid secret. In this real way, you control who calls these API operations. Public applications may use a confidential app client by implementing a lightweight proxy layer while watching Amazon Cognito endpoint, and using this proxy to include a secret hash in relevant requests before passing the requests to Amazon Cognito.

You can find multiple options which you can use to implement this proxy. One option is by using Amazon CloudFront and Lambda@Edge to include the trick hash to the incoming requests. By using a CloudFront proxy, you should use &lt also;a href=”https://aws.amazon.com/waf/” target=”_blank” rel=”noopener noreferrer”>AWS WAF, gives you tools to block and detect unwanted clients. From Lambda@Edge, you can even integrate with other services (like Amazon Fraud Detector or third-party bot detection services) to assist you detect possible fraudulent requests and block them. The CloudFront proxy, with the proper group of security tools, helps guard your Amazon Cognito user pool from unwanted clients.

Solution overview

To implement this lightweight proxy pattern, you will need to create a credit card applicatoin client with a secret. Unauthenticated API calls to the client must are the secret hash that is put into the request from the proxy layer. Client applications use an SDK like AWS Amplify, the Amazon Cognito Identity SDK, or perhaps a mobile SDK to talk to Amazon Cognito. Automagically, the SDK sends requests to the Regional Amazon Cognito endpoint. The application must override the default endpoint by manually adding an “Endpoint” property in the app configuration. Start to see the Integrate your client application with the proxy section in this article for additional information later.

Figure 1 shows how this ongoing works, step-by-step.

Figure 1: A proxy treatment for the Amazon Cognito Regional endpoint

Figure 1: A proxy treatment for the Amazon Cognito Regional endpoint

The workflow is really as follows:

  1. You configure your client application (mobile or web client) to employ a CloudFront endpoint as a proxy to an Amazon Cognito Regional endpoint. You create a credit card applicatoin client in Amazon Cognito with a secret also. Which means that any unauthenticated API call will need to have the trick hash.
  2. Clients that send unauthenticated API calls to the Amazon Cognito endpoint directly are blocked and dropped due to the missing secret.
  3. You utilize Lambda@Edge to include a secret hash to the relevant incoming requests before passing them to the Amazon Cognito endpoint.
  4. From Lambda@Edge, you’ll want the app client secret in order to calculate the trick hash and add it to the request. It’s recommended that the trick is kept by you in AWS Secrets Manager and cache it for the duration of the event.
  5. You utilize AWS WAF with CloudFront distribution to enforce rate limiting, allow and deny lists, along with other rule groups in accordance with your security requirements.

When to utilize this pattern

It’s a best practice to utilize this proxy pattern with clients that use SDKs to integrate with Amazon Cognito user pools. For example mobile applications that utilize the Android or iOS SDK, or web applications that use client-side libraries like Amplify or the Amazon Cognito Identity SDK to integrate with Amazon Cognito.

You don’t have to work with a proxy pattern with server-side applications that use an AWS SDK to integrate with Amazon Cognito user pools from the protected backend, because server-side applications may use confidential clients and protect the trick in the backend natively.

This solution can’t be utilized by you with applications that use Hosted UI and OAuth 2.0 endpoints to integrate with Amazon Cognito user pools. This consists of federation scenarios where users register having an external identity provider (IdP).

Implementation and deployment details

Before you deploy this solution, you will need a user &lt and pool;a href=”https://docs.aws.amazon.com/cognito/latest/developerguide/user-pool-settings-client-apps.html” target=”_blank” rel=”noopener noreferrer”>a credit card applicatoin client that has your client secret. When you yourself have these in place, pick the following Launch Stack button to launch a CloudFormation stack in your account and deploy the proxy solution.

Choose the Launch Stack button to launch the template

Note: The CloudFormation stack should be created in the us-east-1 AWS Region, however the user pool itself can exist in virtually any supported Region.

The parameters are taken by the template shown in Figure 2 below.

Figure 2: CloudFormation stack creation with initial parameters

Figure 2: CloudFormation stack creation with initial parameters

The parameters in Figure 2 include:

This template creates several resources in your AWS account, the following:

  1. A CloudFront distribution that serves as a proxy to an Amazon Cognito Regional endpoint.
  2. An AWS WAF web access control list (ACL) with rules for the allow list, deny list, and rate limit.
  3. A Lambda function to be deployed at the edge and assigned to the foundation request event.
  4. A secret in Secrets Manager, to carry the values of the application form client user and secret pool ID.

Following the stack is established by you, the CloudFront distribution domain name can be acquired on the Outputs tab in the CloudFront console, as shown in Figure 3. This is actually the value that’s used since the Endpoint property in your client-side application. You can &lt optionally;a href=”https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-https-alternate-domain-names.html” target=”_blank” rel=”noopener noreferrer”>add an alternative solution domain name to the CloudFront distribution if you like to use your personal custom domain.

Figure 3: The output of the CloudFormation stack creation, displaying the CloudFront domain name

Figure 3: The output of the CloudFormation stack creation, displaying the CloudFront domain name

Use Lambda@Edge to include a secret hash to the request

As explained earlier, the goal of having this proxy is usually to be able to inject the trick hash in unauthenticated API calls before passing them to the Amazon Cognito endpoint. This injection is attained by a Lambda function that intercepts incoming requests at the edge (the CloudFront distribution) before passing them to the foundation (the Amazon Cognito Regional endpoint).

The Lambda function that’s deployed to the edge has two versions. One is really a simple pass-through proxy that only adds the trick hash, which version can be used if Amazon Cognito advanced security isn’t enabled. Another version is really a proxy that uses the AdminInitiateAuth and AdminRespondToAuthChallenge API operations rather than unauthenticated API operations for an individual authentication and challenge response. This enables the proxy layer to propagate your client Ip to the Amazon Cognito endpoint, which guides the adaptive authentication features of advanced security. The version that’s deployed by&amp by the stack is set;nbsp;the AdvancedSecurityEnabled flag once you create or update the CloudFormation stack.

It is possible to extend this solution by modifying the Lambda function with your personal processing logic manually. For example, it is possible to integrate with fraud detection or bot detection services to judge the request and opt to proceed or reject the decision. Remember that after making any noticeable change to the Lambda function code, you must deploy a fresh version to the edge location. To achieve that from the Lambda console, navigate to Actions, choose Deploy to Lambda@Edge, and choose &lt then;strong>Use existing CloudFront trigger with this function.

Important: If you update the stack from CloudFormation and change the worthiness of the AdvancedSecurityEnabled flag, the brand new value overrides the Lambda code with the default version for the decision. In that full case, all manual changes are lost.

Block or allow requests

The template that’s provided in this website post creates a web ACL with three rules: AllowList, DenyList, and RateLimit. These rules are evaluated to be able and determine which requests are blocked or allowed. The template creates four IP sets, as shown in Figure 4, to carry the values of allowed or blocked IPs for both IPv6 and IPv4 address types.

Figure 4: The CloudFormation template creates IP sets in the AWS WAF console for allow and deny lists

Figure 4: The CloudFormation template creates IP sets in the AWS WAF console for allow and deny lists

If you wish to allow requests from certain clients always, for instance, trusted enterprise clients or server-side clients where a large level of requests is from the same IP address such as a VPN gateway, add these IP addresses to the corresponding AllowList IP set. Similarly, if you wish to block traffic from certain IPs always, add those IPs to the corresponding DenyList IP set.

Requests from sources that aren’t on the allow list or deny list are evaluated in line with the level of calls within five minutes, and sources that exceed the defined rate limit within five minutes are automatically blocked. If you wish to change the defined rate limit, you can certainly do so by updating the CloudFormation stack and providing another value for the RateLimit parameter. Or it is possible to modify this value in the AWS WAF console by editing the RateLimit rule directly.

Note: You can use&amp also;nbsp;AWS Managed Rules for AWS WAF to include additional protection in accordance with your security needs.

Integrate your client application with the proxy

It is possible to integrate your client application with the proxy by changing the Endpoint in your client application to utilize the CloudFront distribution domain name. The domain name is situated in the Outputs portion of the CloudFormation stack.

Afterward you have to edit your client-side code to calls to Amazon Cognito through the proxy endpoint forward. For instance, if you’re utilizing the Identity SDK, this property ought to be changed by you the following.

var poolData = 
     

UserPoolId: ‘ ‘,
ClientId: ‘ ‘,
endpoint: ‘https:// ‘
;

        If you’re using AWS Amplify, the endpoint could be changed by you in the aws-exports.js file by overriding the house aws_cognito_endpoint. Or, if you configure Amplify Auth in your code, the endpoint could be provided by you the following.

 

Amplify.Auth.configure(
     

userPoolId: ‘ ‘,
userPoolWebClientId: ‘ ‘,
endpoint: ‘https:// ‘
);

When you have a mobile application that uses the Amplify mobile SDK, it is possible to override the endpoint in your configuration the following (don’t include AppClientSecret parameter in your configuration). Remember that the Endpoint value provides the domain name only, not the entire URL. This feature comes in the most recent releases of the iOS and Android SDKs.

     "CognitoUserPool": 
  "Default": 
    "AppClientId": "                                                            ",
              "Endpoint": "                                                            ",     
    "PoolId": "                                                            ",
    "Region": "                                                            "
 

Warning:  The Amplify CLI overwrites customizations to the awsconfiguration. amplifyconfiguration and json .json files should you choose an amplify push or amplify pull operation. You need to manually re-apply the Endpoint customization and take away the AppClientSecret if you are using the CLI to change your cloud backend.

Solution limitations

This solution has these limitations:

  • If advanced security features are enabled for an individual pool, Amazon Cognito calculates risk for user events. If you are using this proxy pattern, the Ip that’s propagated in user events may be the proxy IP address, which in turn causes risk calculation for SignUp, ForgotPassword, and ResendCode events to be inaccurate. Alternatively, Sign-In events still have your client Ip propagated correctly, and risk calculation and adaptive authentication for Sign-In events aren’t suffering from the usage of this proxy.
  • This solution isn’t applicable to Hosted UI, OAuth 2.0 endpoints, and federation flows.
  • Authenticated and admin API operations (which require developer credentials or an access token) aren’t covered in this solution. These API operations don’t need a secret hash, plus they use other authentication mechanisms.
  • By using this proxy solution with mobile apps requires an update to the application form. The update might take time to be accessible in the relevant app store, and you must be determined by customers to update their app. Plan in advance to use the answer with mobile apps.

How exactly to detect unusual behavior

In this section, I give out the steps to detect, analyze and react to unwanted clients quickly. It’s a best practice to configure alarms and monitoring that enable you to detect unexpected spikes in activity. Additionally, I demonstrate how to prepare yourself to quickly identify clients which are calling your resources at a higher-than-usual rate.

Monitor utilization in comparison to quotas

Amazon Cognito integrates with Service Quotas , which monitor service utilization in comparison to quotas. These metrics assist you to detect unexpected spikes and become alerted if you’re approaching your quota for a particular API category. Approaching your quota indicates that there surely is a risk that calls from legitimate users will be throttled.

To see utilization versus quota metrics

  1. In the Service Quotas console, choose Service Quotas , choose AWS Services , and choose Amazon Cognito User Pools .
  2. Under Service quotas , enter the key phrase rate of . This teaches you the set of API categories and the assigned quotas for every category.

    Figure 5: The Service Quotas console showing Amazon Cognito API category rate quotas

    Figure 5: The Service Quotas console showing Amazon Cognito API category rate quotas

  3. Choose the API categories to see utilization versus quota metrics.

    Figure 6: The Service Quotas console showing utilization vs quota metrics for Amazon Cognito UserCreation APIs

    Figure 6: The Service Quotas console showing utilization vs quota metrics for Amazon Cognito UserCreation APIs

  4. You can even create alarms out of this page to alert you if utilization is above a pre-defined threshold. It is possible to create alarms starting at 50 percent utilization. It’s recommended that you create multiple alarms, for instance at the 50 percent, 70 percent, and 90 percent thresholds, and configure CloudWatch alarms as appropriate.

    Figure 7: Creating an alarm for the utilization of the UserCreation API category

    Figure 7: Creating an alarm for the use of the UserCreation API category

Analyze CloudTrail logs with Athena

In the event that you detect an urgent spike in traffic to a particular API category, the next thing is to identify the resources of this spike. You can certainly do that through the use of CloudTrail logs or, once you deploy and utilize this proxy solution, CloudFront logs as resources of information. After that you can analyze these logs through the use of Amazon Athena queries.

Step one would be to create Athena tables from CloudFront and CloudTrail logs. You can certainly do that by following these steps for CloudTrail and similar steps for CloudFront . Once you’ve these tables created, a collection can be developed by you of queries that assist you to identify unwanted clients. Here are several examples:

  • Utilize the following query to recognize clients with the best call rate to the InitiateAuth API operation within the timeframe you noticed the spike (change the eventtime value to reflect the attack window).
         SELECT sourceipaddress, count(          )
    

    FROM “default”.”cloudtrail_logs”
    WHERE eventname=’InitiateAuth’
    AND eventtime >= ‘2021-03-01T00:00:00Z’and eventtime < ‘2021-03-31T00:00:00Z’
    GROUP BY sourceipaddress
    LIMIT 10

  • Utilize the following query to recognize clients which come through CloudFront with the best error rate.
         SELECT count() as count, request_ip
    FROM "default"."cloudfront_logs"
    WHERE status>500
    GROUP BY request_ip
         

Once you identify sources which are calling your service with a higher-than-usual rate, it is possible to block these clients with the addition of them to the DenyList IP set that has been created in AWS WAF.

Analyze CloudTrail events with CloudWatch Logs Insights

It’s a best practice to configure your trail to send events to CloudWatch Logs . Once you do this, it is possible to interactively search and analyze your Amazon Cognito CloudTrail events with CloudWatch Logs Insights to recognize errors, unusual activity, or unusual user behavior in your account.

Conclusion

In this article, You’re showed by me how exactly to implement a lightweight proxy to an Amazon Cognito endpoint, which can be used in combination with a credit card applicatoin client secret to regulate usage of unauthenticated API operations. This process, with security tools such as for example AWS WAF together, helps provide protection for these API operations from unwanted clients. I also showed you ways of help detect a continuing attack and quickly analyze, identify, and block unwanted clients.

For more approaches for DDoS mitigation, see the  AWS GUIDELINES for DDoS Resiliency .

When you have feedback concerning this post, submit comments in the Comments section below. When you have questions concerning this post, take up a new thread on the Amazon Cognito forum or contact AWS Support .

Want more AWS Security how-to content, news, and show announcements? Follow us on Twitter .