

**Introducing a new console experience for AWS WAF**

You can now use the updated experience to access AWS WAF functionality anywhere in the console. For more details, see [Working with the console](https://docs.aws.amazon.com/waf/latest/developerguide/working-with-console.html). 

# Client application integrations in AWS WAF
<a name="waf-application-integration"></a>

This section explains how to use the intelligent threat integration APIs and JavaScript CAPTCHA integration API with your AWS WAF features. 

Use AWS WAF client application integration APIs to couple client-side protections with your AWS server-side protection pack (web ACL) protections, to help verify that the client applications that send web requests to your protected resources are the intended clients and that your end users are human beings. 

Use the client integrations to manage silent browser challenges and CAPTCHA puzzles, obtain tokens with proof of successful browser and end user responses, and to include these tokens in requests to your protected endpoints. For general information about AWS WAF tokens, see [Token use in AWS WAF intelligent threat mitigation](waf-tokens.md). 

Combine your client integrations with protection pack (web ACL) protections that require valid tokens for access to your resources. You can use rule groups that check and monitor challenge tokens, like the ones listed in the next section, at [Intelligent threat integration and AWS Managed Rules](waf-application-integration-with-AMRs.md), and you can use the CAPTCHA and Challenge rule actions to check, as described in [CAPTCHA and Challenge in AWS WAF](waf-captcha-and-challenge.md). 

AWS WAF provides two levels of integration for JavaScript applications, and one for mobile applications: 
+ **Intelligent threat integration** – Verify the client application and provide AWS token acquisition and management. This is similar to the functionality provided by the AWS WAF Challenge rule action. This functionality fully integrates your client application with the `AWSManagedRulesACFPRuleSet` managed rule group, the `AWSManagedRulesATPRuleSet` managed rule group, and the targeted protection level of the `AWSManagedRulesBotControlRuleSet` managed rule group. 

  The intelligent threat integration APIs use the AWS WAF silent browser challenge to help ensure that login attempts and other calls to your protected resource are only allowed after the client has acquired a valid token. The APIs manage token authorization for your client application sessions and gather information about the client to help determine whether it's being operated by a bot or by a human being. 
**Note**  
This is available for JavaScript and for Android and iOS mobile applications. 
+ **CAPTCHA integration** – Verify end users with customized CAPTCHA puzzle that you manage in your application. This is similar to the functionality provided by the AWS WAF CAPTCHA rule action, but with added control over the puzzle placement and behavior. 

  This integration leverages the JavaScript intelligent threat integration to run silent challenges and provide AWS WAF tokens to the customer's page. 
**Note**  
This is available for JavaScript applications. 

**Topics**
+ [Intelligent threat integration and AWS Managed Rules](waf-application-integration-with-AMRs.md)
+ [Accessing the AWS WAF client application integration APIs](waf-application-integration-location-in-console.md)
+ [AWS WAF JavaScript integrations](waf-javascript-api.md)
+ [AWS WAF mobile application integration](waf-mobile-sdk.md)

# Intelligent threat integration and AWS Managed Rules
<a name="waf-application-integration-with-AMRs"></a>

This section explains how the intelligent threat integration APIs work with the AWS Managed Rules rule groups.

The intelligent threat integration APIs work with protection packs (web ACLs) that use the intelligent threat rule groups to enable the full functionality of these advanced managed rule groups. 
+ AWS WAF Fraud Control account creation fraud prevention (ACFP) managed rule group `AWSManagedRulesACFPRuleSet`. 

  Account creation fraud is an online illegal activity in which an attacker creates invalid accounts in your application for purposes such as receiving sign-up bonuses or impersonating someone. The ACFP managed rule group provides rules to block, label, and manage requests that might be part of fraudulent account creation attempts. The APIs enable fine-tuned client browser verification and human interactivity information that the ACFP rules use to separate valid client traffic from malicious traffic.

  For more information, see [AWS WAF Fraud Control account creation fraud prevention (ACFP) rule group](aws-managed-rule-groups-acfp.md) and [AWS WAF Fraud Control account creation fraud prevention (ACFP)](waf-acfp.md).
+ AWS WAF Fraud Control account takeover prevention (ATP) managed rule group `AWSManagedRulesATPRuleSet`. 

  Account takeover is an online illegal activity in which an attacker gains unauthorized access to a person's account. The ATP managed rule group provides rules to block, label, and manage requests that might be part of malicious account takeover attempts. The APIs enable fine-tuned client verification and behavior aggregation that the ATP rules use to separate valid client traffic from malicious traffic.

  For more information, see [AWS WAF Fraud Control account takeover prevention (ATP) rule group](aws-managed-rule-groups-atp.md) and [AWS WAF Fraud Control account takeover prevention (ATP)](waf-atp.md).
+ Targeted protection level of the AWS WAF Bot Control managed rule group `AWSManagedRulesBotControlRuleSet`. 

  Bots run from self-identifying and useful ones, such as most search engines and crawlers, to malicious bots that operate against your website and don't self-identify. The Bot Control managed rule group provides rules to monitor, label, and manage the bot activity in your web traffic. When you use the targeted protection level of this rule group, the targeted rules use the client session information that the APIs provide to better detect malicious bots. 

  For more information, see [AWS WAF Bot Control rule group](aws-managed-rule-groups-bot.md) and [AWS WAF Bot Control](waf-bot-control.md).

To add one of these managed rule groups to your protection pack (web ACL), see the procedures [Adding the ACFP managed rule group to your web ACL](waf-acfp-rg-using.md), [Adding the ATP managed rule group to your protection pack (web ACL)](waf-atp-rg-using.md), and [Adding the AWS WAF Bot Control managed rule group to your web ACL](waf-bot-control-rg-using.md).

**Note**  
The managed rule groups currently don't block requests that are missing tokens. In order to block requests that are missing tokens, after you implement your application integration APIs, follow the guidance at [Blocking requests that don't have a valid AWS WAF token](waf-tokens-block-missing-tokens.md). 

# Accessing the AWS WAF client application integration APIs
<a name="waf-application-integration-location-in-console"></a>

This section explains where to find the application integration APIs in the AWS WAF console.

The JavaScript integration APIs are generally available, and you can use them for your browsers and other devices that execute JavaScript. 

AWS WAF offers custom intelligent threat integration SDKs for Android and iOS mobile apps. 
+ For Android mobile and TV apps, the SDKs work for Android API version 23 (Android version 6) and later. For information about Android versions, see [SDK Platform release notes](https://developer.android.com/tools/releases/platforms).
+ For iOS mobile apps, the SDKs work for iOS version 13 and later. For information about iOS versions, see [iOS & iPadOS Release Notes](https://developer.apple.com/documentation/ios-ipados-release-notes).
+ For Apple TV apps, the SDKs work for tvOS version 14 or later. For information about tvOS versions, see [tvOS Release Notes](https://developer.apple.com/documentation/tvos-release-notes).

**To access the integration APIs through the console**

1. Sign in to the AWS Management Console and open the AWS WAF console at [https://console.aws.amazon.com/wafv2/homev2](https://console.aws.amazon.com/wafv2/homev2). 

1. Choose **Application integration** in the navigation pane, and then choose the tab you're interested in.
   + **Intelligent threat integration** is available for JavaScript and mobile applications. 

     The tab contains the following:
     + A list of the protection packs (web ACLs) that are enabled for intelligent threat application integration. The list includes each protection pack (web ACL) that uses the `AWSManagedRulesACFPRuleSet` managed rule group, the `AWSManagedRulesATPRuleSet` managed rule group, or the targeted protection level of the `AWSManagedRulesBotControlRuleSet` managed rule group. When you implement the intelligent threat APIs, you use the integration URL for the protection pack (web ACL) that you want to integrate with.
     + The APIs that you have access to. The JavaScript APIs are always available. For access to the mobile SDKs, contact support at [Contact AWS](https://aws.amazon.com/contact-us).
   + **CAPTCHA integration** is available for JavaScript applications. 

     The tab contains the following: 
     + The integration URL for use in your integration. 
     + The API keys that you've created for your client application domains. Your use of the CAPTCHA API requires an encrypted API key that gives clients the right to access AWS WAF CAPTCHA from their domains. For each client that you integrate with, use an API key that contains the client's domain. For more information these requirements and about managing these keys, see [Managing API keys for the JS CAPTCHA API](waf-js-captcha-api-key.md).

# AWS WAF JavaScript integrations
<a name="waf-javascript-api"></a>

This section explains how to use the AWS WAF JavaScript integrations.

You can use the JavaScript integration APIs to implement AWS WAF application integrations in your browsers and other devices that execute JavaScript. 

CAPTCHA puzzles and silent challenges can only run when browsers are accessing HTTPS endpoints. Browser clients must be running in secure contexts in order to acquire tokens. 
+ The intelligent threat APIs let you manage token authorization through a silent client-side browser challenge, and to include the tokens in the requests that you send to your protected resources. 
+ The CAPTCHA integration API adds to the intelligent threat APIs, and lets you customize the placement and characteristics of the CAPTCHA puzzle in your client applications. This API leverages the intelligent threat APIs to acquire AWS WAF tokens for use in the page after the end user successfully completes the CAPTCHA puzzle. 

By using these integrations, you ensure that the remote procedure calls by your client contain a valid token. When these integration APIs are in place on your application's pages, you can implement mitigating rules in your protection pack (web ACL), such as blocking requests that don't contain a valid token. You can also implement rules that enforce the use of the tokens that your client applications obtain, by using the Challenge or CAPTCHA actions in your rules. 

**Example implementation of intelligent threat APIs**  
The following listing shows basic components of a typical implementation of the intelligent threat APIs in a web application page. 

```
<head>
<script type="text/javascript" src="protection pack (web ACL) integration URL/challenge.js" defer></script>
</head>
<script>
const login_response = await AwsWafIntegration.fetch(login_url, {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: login_body
  });
</script>
```

**Example implementation of CAPTCHA JavaScript API**  
The CAPTCHA integration API lets you customize your end users' CAPTCHA puzzle experience. The CAPTCHA integration leverages the JavaScript intelligent threat integration, for browser verification and token management, and adds a function for configuring and rendering the CAPTCHA puzzle. 

The following listing shows basic components of a typical implementation of the CAPTCHA JavaScript API in a web application page. 

```
<head>
    <script type="text/javascript" src="<Integration URL>/jsapi.js" defer></script>
</head>

<script type="text/javascript">
    function showMyCaptcha() {
        var container = document.querySelector("#my-captcha-container");
        
        AwsWafCaptcha.renderCaptcha(container, {
            apiKey: "...API key goes here...",
            onSuccess: captchaExampleSuccessFunction,
            onError: captchaExampleErrorFunction,
            ...other configuration parameters as needed...
        });
    }
    
    function captchaExampleSuccessFunction(wafToken) {
        // Use WAF token to access protected resources
        AwsWafIntegration.fetch("...WAF-protected URL...", {
            method: "POST",
            ...
        });
    }
    
    function captchaExampleErrorFunction(error) {
        /* Do something with the error */
    }
</script>

<div id="my-captcha-container">
    <!-- The contents of this container will be replaced by the captcha widget -->
</div>
```

**Topics**
+ [Providing domains for use in the tokens](waf-js-challenge-api-set-token-domain.md)
+ [Using the JavaScript API with content security policies](waf-javascript-api-csp.md)
+ [Using the intelligent threat JavaScript API](waf-js-challenge-api.md)
+ [Using the CAPTCHA JavaScript API](waf-js-captcha-api.md)

# Providing domains for use in the tokens
<a name="waf-js-challenge-api-set-token-domain"></a>

This section explains how to provide additional domains for tokens.

By default, when AWS WAF creates a token, it uses the host domain of the resource that’s associated with the protection pack (web ACL). You can provide additional domains for the tokens that AWS WAF creates for the JavaScript APIs. To do this, configure the global variable `window.awsWafCookieDomainList`, with one or more token domains. 

When AWS WAF creates a token, it uses the most appropriate, shortest domain from among the combination of the domains in `window.awsWafCookieDomainList` and the host domain of the resource that’s associated with the protection pack (web ACL). 

Example settings: 

```
window.awsWafCookieDomainList = ['.aws.amazon.com']
```

```
window.awsWafCookieDomainList = ['.aws.amazon.com', 'abc.aws.amazon.com']
```

You can't use public suffixes in this list. For example, you can't use `gov.au` or `co.uk` as token domains in the list.

The domains that you specify in this list must be compatible with your other domains and domain configurations: 
+ The domains must be ones that AWS WAF will accept, based on the protected host domain and the token domain list that's configured for the protection pack (web ACL). For more information, see [AWS WAF protection pack (web ACL) token domain list configuration](waf-tokens-domains.md#waf-tokens-domain-lists). 
+ If you use the JavaScript CAPTCHA API, at least one domain in your CAPTCHA API key must be an exact match for one of the token domains in `window.awsWafCookieDomainList` or it must be the apex domain of one of those token domains. 

  For example, for the token domain `mySubdomain.myApex.com`, the API key `mySubdomain.myApex.com` is an exact match and the API key `myApex.com` is the apex domain. Either key matches the token domain. 

  For more information about the API keys, see [Managing API keys for the JS CAPTCHA API](waf-js-captcha-api-key.md). 

If you use the `AWSManagedRulesACFPRuleSet` managed rule group, you might configure a domain that matches the one in the account creation path that you provided to the rule group configuration. For more information about this configuration, see [Adding the ACFP managed rule group to your web ACL](waf-acfp-rg-using.md).

If you use the `AWSManagedRulesATPRuleSet` managed rule group, you might configure a domain that matches the one in the login path that you provided to the rule group configuration. For more information about this configuration, see [Adding the ATP managed rule group to your protection pack (web ACL)](waf-atp-rg-using.md).

# Using the JavaScript API with content security policies
<a name="waf-javascript-api-csp"></a>

This section provides an example configuration to allowlist the AWS WAF apex domain.

If you apply content security policies (CSP) to your resources, for your JavaScript implementation to work, you need to allowlist the AWS WAF apex domain `awswaf.com`. The JavaScript SDKs make calls to different AWS WAF endpoints, so allowlisting this domain provides the permissions that the SDKs need to operate.

The following shows an example configuration to allowlist the AWS WAF apex domain: 

```
connect-src 'self' https://*.awswaf.com;
script-src 'self' https://*.awswaf.com;
script-src-elem 'self' https://*.awswaf.com;
```

If you try to use the JavaScript SDKs with resources that use CSP, and you haven't allowlisted the AWS WAF domain, you'll receive errors like the following: 

```
Refused to load the script ...awswaf.com/<> because it violates the following Content Security Policy directive: “script-src ‘self’
```

# Using the intelligent threat JavaScript API
<a name="waf-js-challenge-api"></a>

This section provides instructions for using the intelligent threat JavaScript API in your client application.

The intelligent threat APIs provide operations for running silent challenges against the user's browser, and for handling the AWS WAF tokens that provide proof of successful challenge and CAPTCHA responses. 

Implement the JavaScript integration first in a test environment, then in production. For additional coding guidance, see the sections that follow. 

 

**To use the intelligent threat APIs**

1. **Install the APIs** 

   If you use the CAPTCHA API, you can skip this step. When you install the CAPTCHA API, the script automatically installs the intelligent threat APIs.

   1. Sign in to the AWS Management Console and open the AWS WAF console at [https://console.aws.amazon.com/wafv2/homev2](https://console.aws.amazon.com/wafv2/homev2). 

   1. In the navigation pane, choose **Application integration**. On the **Application integration** page, you can see tabbed options. 

   1. Select **Intelligent threat integration**

   1. In the tab, select the protection pack (web ACL) that you want to integrate with. The protection pack (web ACL) list includes only protection packs (web ACLs) that use the `AWSManagedRulesACFPRuleSet` managed rule group, the `AWSManagedRulesATPRuleSet` managed rule group, or the targeted protection level of the `AWSManagedRulesBotControlRuleSet` managed rule group. 

   1. Open the **JavaScript SDK** pane, and copy the script tag for use in your integration. 

   1. In your application page code, in the `<head>` section, insert the script tag that you copied for the protection pack (web ACL). This inclusion causes your client application to automatically retrieve a token in the background on page load. 

      ```
      <head>
          <script type="text/javascript" src="protection pack (web ACL) integration URL/challenge.js” defer></script>
      <head>
      ```

      This `<script>` listing is configured with the `defer` attribute, but you can change the setting to `async` if you want a different behavior for your page. 

1. **(Optional) Add domain configuration for the client's tokens** – By default, when AWS WAF creates a token, it uses the host domain of the resource that’s associated with the protection pack (web ACL). To provide additional domains for the JavaScript APIs, follow the guidance at [Providing domains for use in the tokens](waf-js-challenge-api-set-token-domain.md). 

1. **Code your intelligent threat integration** – Write your code to ensure that token retrieval completes before the client sends its requests to your protected endpoints. If you are already using the `fetch` API to make your call, you can substitute the AWS WAF integration `fetch` wrapper. If you don't use the `fetch` API, you can use the AWS WAF integration `getToken` operation instead. For coding guidance, see the following sections. 

1. **Add token verification in your protection pack (web ACL)** – Add at least one rule to your protection pack (web ACL) that checks for a valid challenge token in the web requests that your client sends. You can use rule groups that check and monitor challenge tokens, like the targeted level of the Bot Control managed rule group, and you can use the Challenge rule action to check, as described in [CAPTCHA and Challenge in AWS WAF](waf-captcha-and-challenge.md). 

   The protection pack (web ACL) additions verify that requests to your protected endpoints include the token that you've acquired in your client integration. Requests that include a valid, unexpired token pass the Challenge inspection and do not send another silent challenge to your client. 

1. **(Optional) Block requests that are missing tokens** – If you use the APIs with the ACFP managed rule group, the ATP managed rule group, or the targeted rules of the Bot Control rule group, these rules don't block requests that are missing tokens. To block requests that are missing tokens, follow the guidance at [Blocking requests that don't have a valid AWS WAF token](waf-tokens-block-missing-tokens.md). 

**Topics**
+ [Intelligent threat API specification](waf-js-challenge-api-specification.md)
+ [How to use the integration `fetch` wrapper](waf-js-challenge-api-fetch-wrapper.md)
+ [How to use the integration `getToken`](waf-js-challenge-api-get-token.md)

# Intelligent threat API specification
<a name="waf-js-challenge-api-specification"></a>

This section lists the specification for the methods and properties of the intelligent threat mitigation JavaScript APIs. Use these APIs for intelligent threat and CAPTCHA integrations.

**`AwsWafIntegration.fetch()`**  
Sends the HTTP `fetch` request to the server using the AWS WAF integration implementation. 

**`AwsWafIntegration.getToken()`**  
Retrieves the stored AWS WAF token and stores it in a cookie on the current page with name `aws-waf-token`, and the value set to the token value. 

**`AwsWafIntegration.hasToken()`**  
Returns a boolean indicating whether the `aws-waf-token` cookie currently holds an unexpired token. 

If you're also using the CAPTCHA integration, see the specification for that at [CAPTCHA JavaScript API specification](waf-js-captcha-api-specification.md).

# How to use the integration `fetch` wrapper
<a name="waf-js-challenge-api-fetch-wrapper"></a>

This section provides instructions for using the integration `fetch` wrapper.

You can use the AWS WAF `fetch` wrapper by changing your normal `fetch` calls to the `fetch` API under the `AwsWafIntegration` namespace. The AWS WAF wrapper supports all of the same options as the standard JavaScript `fetch` API call and adds the token handling for the integration. This approach is generally the simplest way to integrate your application. 

**Before the wrapper implementation**  
The following example listing shows standard code before implementing the `AwsWafIntegration` `fetch` wrapper.

```
const login_response = await fetch(login_url, {
	    method: 'POST',
	    headers: {
	      'Content-Type': 'application/json'
	    },
	    body: login_body
	  });
```

**After the wrapper implementation**  
The following listing shows the same code with the `AwsWafIntegration` `fetch` wrapper implementation.

```
const login_response = await AwsWafIntegration.fetch(login_url, {
	    method: 'POST',
	    headers: {
	      'Content-Type': 'application/json'
	    },
	    body: login_body
	  });
```

# How to use the integration `getToken`
<a name="waf-js-challenge-api-get-token"></a>

This section explains how to use the `getToken` operation.

AWS WAF requires your requests to protected endpoints to include the cookie named `aws-waf-token` with the value of your current token. 

The `getToken` operation is an asynchronous API call that retrieves the AWS WAF token and stores it in a cookie on the current page with name `aws-waf-token`, and the value set to the token value. You can use this token cookie as needed in your page. 

When you call `getToken`, it does the following: 
+ If an unexpired token is already available, the call returns it immediately.
+ Otherwise, the call retrieves a new token from the token provider, waiting for up to 2 seconds for the token acquisition workflow to complete before timing out. If the operation times out, it throws an error, which your calling code must handle. 

The `getToken` operation has an accompanying `hasToken` operation, which indicates whether the `aws-waf-token` cookie currently holds an unexpired token. 

`AwsWafIntegration.getToken()` retrieves a valid token and stores it as a cookie. Most client calls automatically attach this cookie, but some don't. For example, calls made across host domains don't attach the cookie. In the implementation details that follow, we show how to work with both types of client calls. 

**Basic `getToken` implementation, for calls that attach the `aws-waf-token` cookie**  
The following example listing shows standard code for implementing the `getToken` operation with a login request.

```
const login_response = await AwsWafIntegration.getToken()
	    .catch(e => {
	        // Implement error handling logic for your use case
	    })
	    // The getToken call returns the token, and doesn't typically require special handling
	    .then(token => {
	        return loginToMyPage()
	    })
	
	async function loginToMyPage() {
	    // Your existing login code
	}
```

**Submit form only after token is available from `getToken`**  
The following listing shows how to register an event listener to intercept form submissions until a valid token is available for use. 

```
<body>
	  <h1>Login</h1>
	  <p></p>
	  <form id="login-form" action="/web/login" method="POST" enctype="application/x-www-form-urlencoded">
	    <label for="input_username">USERNAME</label>
	    <input type="text" name="input_username" id="input_username"><br>
	    <label for="input_password">PASSWORD</label>
	    <input type="password" name="input_password" id="input_password"><br>
	    <button type="submit">Submit<button>
	  </form>
	
	<script>
	  const form = document.querySelector("#login-form");
	
	  // Register an event listener to intercept form submissions
	  form.addEventListener("submit", (e) => {
	      // Submit the form only after a token is available 
	      if (!AwsWafIntegration.hasToken()) {
	          e.preventDefault();
	          AwsWafIntegration.getToken().then(() => {
	              e.target.submit();
	          }, (reason) => { console.log("Error:"+reason) });
	        }
	    });
	</script>
	</body>
```

**Attaching the token when your client doesn't attach the `aws-waf-token` cookie by default**  
`AwsWafIntegration.getToken()` retrieves a valid token and stores it as a cookie, but not all client calls attach this cookie by default. For example, calls made across host domains don't attach the cookie. 

The `fetch` wrapper handles these cases automatically, but if you aren't able to use the `fetch` wrapper, you can handle this by using a custom `x-aws-waf-token` header. AWS WAF reads tokens from this header, in addition to reading them from the `aws-waf-token` cookie. The following code shows an example of setting the header. 

```
const token = await AwsWafIntegration.getToken();
const result = await fetch('/url', {
    headers: {
        'x-aws-waf-token': token,
    },
});
```

By default, AWS WAF only accepts tokens that contain the same domain as the requested host domain. Any cross-domain tokens require corresponding entries in the protection pack (web ACL) token domain list. For more information, see [AWS WAF protection pack (web ACL) token domain list configuration](waf-tokens-domains.md#waf-tokens-domain-lists). 

For additional information about cross-domain token use, see [aws-samples/aws-waf-bot-control-api-protection-with-captcha](https://github.com/aws-samples/aws-waf-bot-control-api-protection-with-captcha).

# Using the CAPTCHA JavaScript API
<a name="waf-js-captcha-api"></a>

This section provides instructions for using the CAPTCHA integration API.

The CAPTCHA JavaScript API allows you to configure the CAPTCHA puzzle and place it where you want in your client application. This API leverages the features of the intelligent threat JavaScript APIs to acquire and use AWS WAF tokens after an end user successfully completes a CAPTCHA puzzle. 

Implement the JavaScript integration first in a test environment, then in production. For additional coding guidance, see the sections that follow. 

**To use the CAPTCHA integration API**

1. **Install the API**

   1. Sign in to the AWS Management Console and open the AWS WAF console at [https://console.aws.amazon.com/wafv2/homev2](https://console.aws.amazon.com/wafv2/homev2). 

   1. In the navigation pane, choose **Application integration**. On the **Application integration** page, you can see tabbed options. 

   1. Select **CAPTCHA integration**.

   1. Copy the listed JavaScript integration script tag for use in your integration.

   1. In your application page code, in the `<head>` section, insert the script tag that you copied. This inclusion makes the CAPTCHA puzzle available for configuration and use. 

      ```
      <head>
          <script type="text/javascript" src="integrationURL/jsapi.js" defer></script>
      </head>
      ```

      This `<script>` listing is configured with the `defer` attribute, but you can change the setting to `async` if you want a different behavior for your page. 

      The CAPTCHA script also automatically loads the intelligent threat integration script if it isn't already present. The intelligent threat integration script causes your client application to automatically retrieve a token in the background on page load, and provides other token management functionality that you need for your use of the CAPTCHA API. 

1. **(Optional) Add domain configuration for the client's tokens** – By default, when AWS WAF creates a token, it uses the host domain of the resource that’s associated with the protection pack (web ACL). To provide additional domains for the JavaScript APIs, follow the guidance at [Providing domains for use in the tokens](waf-js-challenge-api-set-token-domain.md). 

1. **Get the encrypted API key for the client** – The CAPTCHA API requires an encrypted API key that contains a list of valid client domains. AWS WAF uses this key to verify that the client domain you're using with the integration is approved to use AWS WAF CAPTCHA. To generate your API key, follow the guidance at [Managing API keys for the JS CAPTCHA API](waf-js-captcha-api-key.md).

1. **Code your CAPTCHA widget implementation** – Implement the `renderCaptcha()` API call in your page, at the location where you want to use it. For information about configuring and using this function, see the following sections, [CAPTCHA JavaScript API specification](waf-js-captcha-api-specification.md) and [How to render the CAPTCHA puzzle](waf-js-captcha-api-render.md). 

   The CAPTCHA implementation integrates with the intelligent threat integration APIs for token management and to run fetch calls that use the AWS WAF tokens. For guidance about using these APIs, see [Using the intelligent threat JavaScript API](waf-js-challenge-api.md).

1. **Add token verification in your protection pack (web ACL)** – Add at least one rule to your protection pack (web ACL) that checks for a valid CAPTCHA token in the web requests that your client sends. You can use the CAPTCHA rule action to check, as described in [CAPTCHA and Challenge in AWS WAF](waf-captcha-and-challenge.md). 

   The protection pack (web ACL) additions verify that requests going to your protected endpoints include the token that you've acquired in your client integration. Requests that include a valid, unexpired CAPTCHA token pass the CAPTCHA rule action inspection and do not present your end user with another CAPTCHA puzzle. 

After you've implemented the JavaScript API, you can review the CloudWatch metrics for CAPTCHA puzzle attempts and solutions. For metrics and dimension details, see [Account metrics and dimensions](waf-metrics.md#waf-metrics-account).

**Topics**
+ [CAPTCHA JavaScript API specification](waf-js-captcha-api-specification.md)
+ [How to render the CAPTCHA puzzle](waf-js-captcha-api-render.md)
+ [Handling a CAPTCHA response from AWS WAF](waf-js-captcha-api-conditional.md)
+ [Managing API keys for the JS CAPTCHA API](waf-js-captcha-api-key.md)

# CAPTCHA JavaScript API specification
<a name="waf-js-captcha-api-specification"></a>

This section lists the specification for the methods and properties of the CAPTCHA JavaScript APIs. Use the CAPTCHA JavaScript APIs to run custom CAPTCHA puzzles in your client applications. 

This API builds on the intelligent threat APIs, which you use to configure and manage AWS WAF token acquisition and use. See [Intelligent threat API specification](waf-js-challenge-api-specification.md). .

**`AwsWafCaptcha.renderCaptcha(container, configuration)`**  
Presents an AWS WAF CAPTCHA puzzle to the end user and, upon success, updates the client token with the CAPTCHA validation. This is available only with the CAPTCHA integration. Use this call along with the intelligent threat APIs to manage token retrieval and to provide the token in your `fetch` calls. See the intelligent threat APIs at [Intelligent threat API specification](waf-js-challenge-api-specification.md).  
Unlike the CAPTCHA interstitial that AWS WAF sends, the CAPTCHA puzzle rendered by this method displays the puzzle immediately, without an initial title screen.     
**`container`**  
The `Element` object for the target container element on the page. This is commonly retrieved by calling `document.getElementById()` or `document.querySelector()`.  
Required: Yes  
Type: `Element`  
**configuration**  
An object containing CAPTCHA configuration settings, as follows****:    
**`apiKey`**   
The encrypted API key that enables permissions for the client's domain. Use the AWS WAF console to generate your API keys for your client domains. You can use one key for up to five domains. For information, see [Managing API keys for the JS CAPTCHA API](waf-js-captcha-api-key.md).   
Required: Yes  
Type: `string`  
**`onSuccess: (wafToken: string) => void;`**   
Called with a valid AWS WAF token when the end user successfully completes a CAPTCHA puzzle. Use the token in the requests that you send to the endpoints that you protect with an AWS WAF protection pack (web ACL). The token provides proof and the timestamp of the latest successful puzzle completion.   
Required: Yes  
**`onError?: (error: CaptchaError) => void;`**   
Called with an error object when an error occurs during the CAPTCHA operation.   
Required: No  
**`CaptchaError` class definition** – The `onError` handler supplies an error type with the following class definition.   

```
CaptchaError extends Error {
    kind: "internal_error" | "network_error" | "token_error" | "client_error";
    statusCode?: number;
}
```
+ `kind` – The kind of error returned. 
+ `statusCode` – The HTTP status code, if available. This is used by `network_error` if the error is due to an HTTP error.  
**`onLoad?: () => void;`**   
Called when a new CAPTCHA puzzle loads.  
Required: No  
**`onPuzzleTimeout?: () => void;`**   
Called when a CAPTCHA puzzle isn't completed before it expires.  
Required: No  
**`onPuzzleCorrect?: () => void;`**   
Called when a correct answer is provided to a CAPTCHA puzzle.  
Required: No  
**`onPuzzleIncorrect?: () => void;`**   
Called when an incorrect answer is provided to a CAPTCHA puzzle.  
Required: No  
**`defaultLocale`**   
The default locale to use for the CAPTCHA puzzle. The written instructions for CAPTCHA puzzles are available in Arabic (ar-SA), simplified Chinese (zh-CN), Dutch (nl-NL), English (en-US), French (fr-FR), German (de-DE), Italian (it-IT), Japanese (ja-JP), Brazilian Portuguese (pt-BR), Spanish (es-ES), and Turkish (tr-TR). Audio instructions are available for all of the written languages except Chinese and Japanese, which default to English. To change the default language, provide the international language and locale code, for example, `ar-SA`.  
Default: The language currently in use in the end user's browser  
Required: No  
Type: `string`  
**`disableLanguageSelector`**   
If set to `true`, the CAPTCHA puzzle hides the language selector.   
Default: `false`  
Required: No  
Type: `boolean`  
**`dynamicWidth`**   
If set to `true`, the CAPTCHA puzzle changes width for compatibility with the browser window width.   
Default: `false`  
Required: No  
Type: `boolean`  
**`skipTitle`**   
If set to `true`, the CAPTCHA puzzle doesn't display the puzzle title heading **Solve the puzzle**.   
Default: `false`  
Required: No  
Type: `boolean`

# How to render the CAPTCHA puzzle
<a name="waf-js-captcha-api-render"></a>

This section provides an example `renderCaptcha` implementation.

You can use the AWS WAF `renderCaptcha` call where you want to in your client interface. The call retrieves a CAPTCHA puzzle from AWS WAF, renders it, and sends the results to AWS WAF for verification. When you make the call, you provide the puzzle rendering configuration and the callbacks that you want to run when your end users complete the puzzle. For details about the options, see the preceding section, [CAPTCHA JavaScript API specification](waf-js-captcha-api-specification.md).

Use this call in conjunction with the token management functionality of the intelligent threat integration APIs. This call gives your client a token that verifies the successful completion of the CAPTCHA puzzle. Use the intelligent threat integration APIs to manage the token and to provide the token in your client's calls to the endpoints that are protected with AWS WAF protection packs (web ACLs). For information about the intelligent threat APIs, see [Using the intelligent threat JavaScript API](waf-js-challenge-api.md).

**Example implementation**  
The following example listing shows a standard CAPTCHA implementation, including the placement of the AWS WAF integration URL in the `<head>` section. 

This listing configures the `renderCaptcha` function with a success callback that uses the `AwsWafIntegration.fetch` wrapper of the intelligent threat integration APIs. For information about this function, see [How to use the integration `fetch` wrapper](waf-js-challenge-api-fetch-wrapper.md).

```
<head>
    <script type="text/javascript" src="<Integration URL>/jsapi.js" defer></script>
</head>

<script type="text/javascript">
    function showMyCaptcha() {
        var container = document.querySelector("#my-captcha-container");
        
        AwsWafCaptcha.renderCaptcha(container, {
            apiKey: "...API key goes here...",
            onSuccess: captchaExampleSuccessFunction,
            onError: captchaExampleErrorFunction,
            ...other configuration parameters as needed...
        });
    }
    
    function captchaExampleSuccessFunction(wafToken) {
        // Captcha completed. wafToken contains a valid WAF token. Store it for
        // use later or call AwsWafIntegration.fetch() to use it easily.
        // It will expire after a time, so calling AwsWafIntegration.getToken()
        // again is advised if the token is needed later on, outside of using the
        // fetch wrapper.
        
        // Use WAF token to access protected resources
        AwsWafIntegration.fetch("...WAF-protected URL...", {
            method: "POST",
            headers: {
                "Content-Type": "application/json",
            },
            body: "{ ... }" /* body content */
        });
    }
    
    function captchaExampleErrorFunction(error) {
        /* Do something with the error */
    }
</script>

<div id="my-captcha-container">
    <!-- The contents of this container will be replaced by the captcha widget -->
</div>
```

**Example configuration settings**  
The following example listing shows the `renderCaptcha` with non-default settings for the width and the title options. 

```
        AwsWafCaptcha.renderCaptcha(container, {
            apiKey: "...API key goes here...",
            onSuccess: captchaExampleSuccessFunction,
            onError: captchaExampleErrorFunction,
            dynamicWidth: true, 
            skipTitle: true
        });
```

For full information about the configuration options, see [CAPTCHA JavaScript API specification](waf-js-captcha-api-specification.md).

# Handling a CAPTCHA response from AWS WAF
<a name="waf-js-captcha-api-conditional"></a>

This section provides an example of handling a CAPTCHA response.

An AWS WAF rule with a CAPTCHA action terminates the evaluation of a matching web request if the request doesn't have a token with a valid CAPTCHA timestamp. If the request is a `GET` text/html call, the CAPTCHA action then serves the client an interstitial with a CAPTCHA puzzle. When you don't integrate the CAPTCHA JavaScript API, the interstitial runs the puzzle and, if the end user successfully solves it, automatically resubmits the request. 

When you integrate the CAPTCHA JavaScript API and customize your CAPTCHA handling, you need to detect the terminating CAPTCHA response, serve your custom CAPTCHA, and then if the end user successfully solves the puzzle, resubmit the client's web request. 

The following code example shows how to do this. 

**Note**  
The AWS WAF CAPTCHA action response has a status code of HTTP 405, which we use to recognize the CAPTCHA response in this code. If your protected endpoint uses an HTTP 405 status code to communicate any other type of response for the same call, this example code will render a CAPTCHA puzzle for those responses as well. 

```
<!DOCTYPE html>
<html>
<head>
    <script type="text/javascript" src="<Integration URL>/jsapi.js" defer></script>
</head>
<body>
    <div id="my-captcha-box"></div>
    <div id="my-output-box"></div>

    <script type="text/javascript">
    async function loadData() {
        // Attempt to fetch a resource that's configured to trigger a CAPTCHA
        // action if the rule matches. The CAPTCHA response has status=HTTP 405.
        const result = await AwsWafIntegration.fetch("/protected-resource");

        // If the action was CAPTCHA, render the CAPTCHA and return

        // NOTE: If the endpoint you're calling in the fetch call responds with HTTP 405
        // as an expected response status code, then this check won't be able to tell the
        // difference between that and the CAPTCHA rule action response.

        if (result.status === 405) {
            const container = document.querySelector("#my-captcha-box");
            AwsWafCaptcha.renderCaptcha(container, {
                apiKey: "...API key goes here...",
                onSuccess() {
                    // Try loading again, now that there is a valid CAPTCHA token
                    loadData();
                },
            });
            return;
        }

        const container = document.querySelector("#my-output-box");
        const response = await result.text();
        container.innerHTML = response;
    }

    window.addEventListener("load", () => {
        loadData();
    });
    </script>
</body>
</html>
```

# Managing API keys for the JS CAPTCHA API
<a name="waf-js-captcha-api-key"></a>

This section provides instructions for generating and deleting API keys.

To integrate AWS WAF CAPTCHA into a a client application with the JavaScript API, you need the JavaScript API integration tag and the encrypted API key for the client domain where you want to run your CAPTCHA puzzle. 

The CAPTCHA application integration for JavaScript uses the encrypted API keys to verify that the client application domain has permission to use the AWS WAF CAPTCHA API. When you call the CAPTCHA API from your JavaScript client, you provide an API key with a domain list that includes a domain for the current client. You can list up to 5 domains in a single encrypted key. 

**API key requirements**  
The API key that you use in your CAPTCHA integration must contain a domain that applies to the client where you use the key. 
+ If you specify a `window.awsWafCookieDomainList` in your client's intelligent threat integration, then at least one domain in your API key must be an exact match for one of the token domains in `window.awsWafCookieDomainList` or it must be the apex domain of one of those token domains. 

  For example, for the token domain `mySubdomain.myApex.com`, the API key `mySubdomain.myApex.com` is an exact match and the API key `myApex.com` is the apex domain. Either key matches the token domain. 

  For information about the setting the token domain list, see [Providing domains for use in the tokens](waf-js-challenge-api-set-token-domain.md).
+ Otherwise, the current domain must be contained in the API key. The current domain is the domain that you can see in the browser address bar. 

The domains that you use must be ones that AWS WAF will accept, based on the protected host domain and the token domain list that's configured for the web ACL. For more information, see [AWS WAF protection pack (web ACL) token domain list configuration](waf-tokens-domains.md#waf-tokens-domain-lists).

**How to choose the Region for your API key**  
AWS WAF can generate CAPTCHA API keys in any Region where AWS WAF is available. 

As a general rule, you should use the same Region for your CAPTCHA API key as you use for your protection pack (web ACL). If you expect a global audience for a regional protection pack (web ACL), however, you can obtain a CAPTCHA JavaScript integration tag that's scoped to CloudFront and an API key that's scoped to CloudFront, and use them with a regional protection pack (web ACL). This approach allows clients to load a CAPTCHA puzzle from the Region that's closest to them, which reduces latency. 

CAPTCHA API keys that are scoped to Regions other than CloudFront are not supported for use across multiple Regions. They can only be used in the Region they are scoped to. 

**To generate an API key for your client domains**  
To obtain the integration URL and generate and retrieve the API keys through the console. 

1. Sign in to the AWS Management Console and open the AWS WAF console at [https://console.aws.amazon.com/wafv2/homev2](https://console.aws.amazon.com/wafv2/homev2). 

1. In the navigation pane, choose **Application integration**. 

1. In the pane, **protection packs (web ACLs) that are enabled for application integration**, select the Region that you want to use for your API key. You can also select the Region in the **API keys** pane of the **CAPTCHA integration** tab.

1. Choose the tab **CAPTCHA integration**. This tab provides the CAPTCHA JavaScript integration tag, which you can use in your integration, and the API keys listing. Both are scoped to the selected Region.

1. In the **API keys** pane, choose **Generate key**. The key generation dialogue appears. 

1. Enter the client domains that you want to include in the key. You can enter up to 5. When you're finished, choose **Generate key**. The interface returns to the CAPTCHA integration tab, where your new key is listed. 

   Once created, an API key is immutable. If you need to make changes to a key, generate a new key and use that instead. 

1. (Optional) Copy the newly generated key for use in your integration. 

You can also use the REST APIs or one of the language-specific AWS SDKs for this work. The REST API calls are [CreateAPIKey](https://docs.aws.amazon.com/waf/latest/APIReference/API_CreateAPIKey.html) and [ListAPIKeys](https://docs.aws.amazon.com/waf/latest/APIReference/API_ListAPIKeys.html). 

**To delete an API key**  
To delete an API key, you must use the REST API or one of the language specific AWS SDKs. The REST API call is [DeleteAPIKey](https://docs.aws.amazon.com/waf/latest/APIReference/API_DeleteAPIKey.html). You can't use the console to delete a key. 

After you delete a key, it can take up to 24 hours for AWS WAF to disallow use of the key in all regions. 

# AWS WAF mobile application integration
<a name="waf-mobile-sdk"></a>

This section introduces the topic of using the AWS WAF mobile SDKs to implement AWS WAF intelligent threat integration SDKs for Android and iOS mobile and TV apps. For TV apps, the SDKs are compatible with major smart TV platforms, including Android TV and Apple TV.
+ For Android mobile and TV apps, the SDKs work for Android API version 23 (Android version 6) and later. For information about Android versions, see [SDK Platform release notes](https://developer.android.com/tools/releases/platforms).
+ For iOS mobile apps, the SDKs work for iOS version 13 and later. For information about iOS versions, see [iOS & iPadOS Release Notes](https://developer.apple.com/documentation/ios-ipados-release-notes).
+ For Apple TV apps, the SDKs work for tvOS version 14 or later. For information about tvOS versions, see [tvOS Release Notes](https://developer.apple.com/documentation/tvos-release-notes).

With the mobile AWS WAF SDK, you can manage token authorization, and include the tokens in the requests that you send to your protected resources. By using the SDKs, you ensure that these remote procedure calls by your client contain a valid token. Additionally, when this integration is in place on your application's pages, you can implement mitigating rules in your protection pack (web ACL), such as blocking requests that don't contain a valid token.

For access to the mobile SDKs, contact support at [Contact AWS](https://aws.amazon.com/contact-us).

**Note**  
The AWS WAF mobile SDKs aren't available for CAPTCHA customization.

The basic approach for using the SDK is to create a token provider using a configuration object, then to use the token provider to retrieve tokens from AWS WAF. By default, the token provider includes the retrieved tokens in your web requests to your protected resource. 

The following is a partial listing of an SDK implementation, which shows the main components. For more detailed examples, see [Code examples for the AWS WAF mobile SDK](waf-mobile-sdk-coding-examples.md).

------
#### [ iOS ]

```
let url: URL = URL(string: "protection pack (web ACL) integration URL")!
	let configuration = WAFConfiguration(applicationIntegrationUrl: url, domainName: "Domain name")
	let tokenProvider = WAFTokenProvider(configuration)
	let token = tokenProvider.getToken()
```

------
#### [ Android ]

```
URL applicationIntegrationURL = new URL("protection pack (web ACL) integration URL");
	String domainName = "Domain name";
	WAFConfiguration configuration = WAFConfiguration.builder().applicationIntegrationURL(applicationIntegrationURL).domainName(domainName).build();
	WAFTokenProvider tokenProvider = new WAFTokenProvider(Application context, configuration);
	WAFToken token = tokenProvider.getToken();
```

------

# Installing the AWS WAF mobile SDK
<a name="waf-mobile-sdk-installing"></a>

This section provides instructions for installing the AWS WAF mobile SDK.

For access to the mobile SDKs, contact support at [Contact AWS](https://aws.amazon.com/contact-us).

Implement the mobile SDK first in a test environment, then in production.

**To install the AWS WAF mobile SDK**

1. Sign in to the AWS Management Console and open the AWS WAF console at [https://console.aws.amazon.com/wafv2/homev2](https://console.aws.amazon.com/wafv2/homev2). 

1. In the navigation pane, choose **Application integration**. 

1. In the **Intelligent threat integrations** tab, do the following: 

   1. In the pane **protection packs (web ACLs) that are enabled for application integration**, locate the protection pack (web ACL) that you're integrating with. Copy and save the protection pack (web ACL) integration URL for use in your implementation. You can also obtain this URL through the API call `GetWebACL`.

   1. Choose the mobile device type and version, then choose **Download**. You can choose any version you like, but we recommend using the latest version. AWS WAF downloads the `zip` file for your device to your standard download location.

1. In your app development environment, unzip the file to a work location of your choice. In the top-level directory of the zip file, locate and open the `README`. Follow the instructions in the `README` file to install the AWS WAF mobile SDK for use in your mobile app code. 

1. Program your app according to the guidance in the following sections.

# AWS WAF mobile SDK specification
<a name="waf-mobile-sdk-specification"></a>

This section lists the SDK objects, operations, and configuration settings for the latest available version of the AWS WAF mobile SDK. For detailed information about how the token provider and operations work for the various combinations of configuration settings, see [How the AWS WAF mobile SDK works](waf-mobile-sdk-how-it-works.md). 

**`WAFToken`**  
Holds an AWS WAF token.    
**`getValue()`**  
Retrieves the `String` representation of the `WAFToken`. 

**`WAFTokenProvider`**  
Manages tokens in your mobile app. Implement this using a `WAFConfiguration` object.    
**`getToken()`**  
If background refresh is enabled, this returns the cached token. If background refresh is disabled, this makes a synchronous, blocking call to AWS WAF to retrieve a new token.   
**`loadTokenIntoProvider(WAFToken)`**  
Loads the specified token into the `WAFTokenProvider`, replacing any token that the provider was managing. The token provider takes ownership of the new token and handles refreshing it going forward. This operation also updates the token in the cookie store, if `setTokenCookie` is enabled in the `WAFConfiguration`.  
**`onTokenReady(WAFTokenResultCallback)`**  
Instructs the token provider to refresh the token and invoke the provided callback when an active token is ready. The token provider will invoke your callback in a background thread when the token is cached and ready. Call this when your app first loads and also when it comes back to an active state. For more information about returning to an active state, see [Retrieving a token following app inactivity](waf-mobile-sdk-how-it-works.md#waf-mobile-sdk-how-back-from-inactive).   
For Android or iOS apps, you can set `WAFTokenResultCallback` to the operation that you want the token provider to invoke when a requested token is ready. Your implementation of `WAFTokenResultCallback` must take the parameters `WAFToken`, `SdkError`. For iOS apps, you can alternately create an inline function.   
**`storeTokenInCookieStorage(WAFToken)`**  
Instructs the `WAFTokenProvider` to store the specified AWS WAF token into the SDK’s cookie manager. By default, the token is only added to the cookie store when it's first acquired and when it's refreshed. If the application clears the shared cookie store for any reason, the SDK doesn't automatically add the AWS WAF token back until the next refresh. 

**`WAFConfiguration`**  
Holds the configuration for the implementation of the `WAFTokenProvider`. When you implement this, you provide your protection pack (web ACL)’s integration URL, the domain name to use in the token, and any non-default settings that you want the token provider to use.   
The following list specifies the configuration settings that you can manage in the `WAFConfiguration` object.    
**`applicationIntegrationUrl`**   
The application integration URL. Get this from the AWS WAF console or through the `getWebACL` API call.  
Required: Yes  
Type: App-specific URL. For iOS, see [iOS URL](https://developer.apple.com/documentation/foundation/url). For Android, see [java.net URL](https://docs.oracle.com/javase/7/docs/api/java/net/URL.html).   
**`backgroundRefreshEnabled`**   
Indicates whether you want the token provider to refresh the token in the background. If you set this, the token provider refreshes your tokens in the background according to the configuration settings that govern automatic token refresh activities.   
Required: No  
Type: `Boolean`  
Default value: `TRUE`  
**`domainName`**   
The domain to use in the token, which is used in token acquisition and cookie storage. For example, `example.com` or `aws.amazon.com`. This is usually the host domain of your resource that’s associated with the protection pack (web ACL), where you’ll be sending web requests. For the ACFP managed rule group, `AWSManagedRulesACFPRuleSet`, this will usually be a single domain that matches the domain in the account creation path that you provided in the rule group configuration. For the ATP managed rule group, `AWSManagedRulesATPRuleSet`, this will usually be a single domain that matches the domain in the login path that you provided in the rule group configuration.   
Public suffixes aren't allowed. For example, you can't use `gov.au` or `co.uk` as the token domain.  
The domain must be one that AWS WAF will accept, based on the protected host domain and the protection pack (web ACL)'s token domain list. For more information, see [AWS WAF protection pack (web ACL) token domain list configuration](waf-tokens-domains.md#waf-tokens-domain-lists).  
Required: Yes  
Type: `String`   
**`maxErrorTokenRefreshDelayMsec`**   
The maximum time in milliseconds to wait before repeating a token refresh after a failed attempt. For each auto-retry for a failed attempt, it will add an exponential backoff up until the given input delay time. This value is used after token retrieval has failed and been retried `maxRetryCount` times.   
Required: No  
Type: `Integer`  
Default value: `5000` (5 seconds)  
Minimum value allowed: `1` (1 millisecond)  
Maximum value allowed: `30000` (30 seconds)  
**`maxRetryCount`**   
The maximum number of retries to perform with exponential backoff when a token is requested.   
Required: No  
Type: `Integer`  
Default value: `Infinity`  
Minimum value allowed: `0`  
Maximum value allowed: `100`  
**`setTokenCookie`**   
Indicates whether you want the SDK’s cookie manager to add a token cookie into requests and in other areas.   
With a `TRUE` value:   
+ The cookie manager adds a token cookie to all requests whose path is under the path specified in `tokenCookiePath`. 
+ The `WAFTokenProvider` operation `loadTokenIntoProvider()` updates the token in the cookie store, in addition to loading it into the token provider.
Required: No  
Type: `Boolean`  
Default value: `TRUE`  
**`tokenCookiePath`**   
Used when `setTokenCookie` is `TRUE`. Indicates the top-level path where you want the SDK’s cookie manager to add a token cookie. The manager adds a token cookie to all requests that you send to this path and to all child paths.   
For example, if you set this to `/web/login`, then the manager includes the token cookie for everything sent to `/web/login` and any of its child paths, like `/web/login/help`. It doesn't include the token for requests sent to other paths, like `/`, `/web`, or `/web/order`.   
Required: No  
Type: `String`  
Default value: `/`  
**`tokenRefreshDelaySec`**   
Used for background refresh. The maximum amount of time in seconds between background token refreshes.  
Required: No  
Type: `Integer`  
Default value: `88`  
Minimum value allowed: `88`  
Maximum value allowed: `300` (5 minutes)

## AWS WAF mobile SDK errors
<a name="waf-mobile-sdk-errors"></a>

This section lists the possible errors for the current AWS WAF mobile SDK version.

**`SdkError`**  
The error type returned when failing to retrieve a token. The Android and iOS SDK have the same error types.  
The AWS WAF mobile SDK has the following error types:    
**`invalidChallenge`**  
This error is returned when the token server returns invalid challenge data, or the response blob is mutated by an attacker.  
**`errorInvokingGetChallengeEndpoint`**  
This error is returned when the token server sends a non-success response code back to the client or when a network error occurs.  
**`invalidVerifyChallengeResponse`**  
This error is returned when there is an error retrieving the `aws-waf-token` from the AWS WAF server's verification response, or the server response was tampered with.  
**`errorInvokingVerifyEndpoint`**  
This error is returned when the client receives a bad response from the AWS WAF server or network error when verifying the solved challenge.  
**`internalError`**  
This error is returned on all other errors that might occur within the SDK itself.

**`socketTimeoutException`**  
This error is often returned when encountering network errors during token retrieval.  
This error might be caused by the following:  
+ Low network bandwidth: Confirm your network connectivity settings
+ Mutated Application Integration URL: Confirm that the integration URL is not modified from what appears on the AWS WAF console

# How the AWS WAF mobile SDK works
<a name="waf-mobile-sdk-how-it-works"></a>

This section explains how the AWS WAF mobile SDK classes, properties, and operations work together.

The mobile SDKs provide you with a configurable token provider that you can use for token retrieval and use. The token provider verifies that the requests that you allow are from legitimate customers. When you send requests to the AWS resources that you protect with AWS WAF, you include the token in a cookie, to validate the request. You can handle the token cookie manually or have the token provider do it for you.

This section covers the interactions between the classes, properties, and methods that are included in the mobile SDK. For the SDK specification, see [AWS WAF mobile SDK specification](waf-mobile-sdk-specification.md). 

## Token retrieval and caching
<a name="waf-mobile-sdk-how-token-basics"></a>

When you create the token provider instance in your mobile app, you configure how you want it to manage tokens and token retrieval. Your main choice is how to maintain valid, unexpired tokens for use in your app’s web requests:
+ **Background refresh enabled** – This is the default. The token provider automatically refreshes the token in the background and caches it. With background refresh enabled, when you call `getToken()`, the operation retrieves the cached token. 

  The token provider performs the token refresh at configurable intervals, so that an unexpired token is always available in the cache while the application is active. Background refresh is paused while your application is in an inactive state. For information about this, see [Retrieving a token following app inactivity](#waf-mobile-sdk-how-back-from-inactive).
+ **Background refresh disabled** – You can disable background token refresh, and then retrieve tokens only on demand. Tokens retrieved on demand aren't cached, and you can retrieve more than one if you want. Each token is independent of any others that you retrieve, and each has its own timestamp that's used to calculate expiration.

  You have the following choices for token retrieval when background refresh is disabled: 
  + **`getToken()`** – When you call `getToken()` with background refresh disabled, the call synchronously retrieves a new token from AWS WAF. This is a potentially blocking call that might affect app responsiveness if you invoke it on the main thread. 
  + **`onTokenReady(WAFTokenResultCallback)`** – This call asynchronously retrieves a new token and then invokes the provided result callback in a background thread when a token is ready. 

### How the token provider retries failed token retrievals
<a name="waf-mobile-sdk-how-token-retrieval-retries"></a>

The token provider automatically retries token retrieval when retrieval fails. Retries are initially performed using exponential backoff with a starting retry wait time of 100 ms. For information about exponential retries, see [Error retries and exponential backoff in AWS](https://docs.aws.amazon.com/general/latest/gr/api-retries.html).

When the number of retries reaches the configured `maxRetryCount`, the token provider either stops trying or switches to trying every `maxErrorTokenRefreshDelayMsec` milliseconds, depending on the type of token retrieval: 
+ **`onTokenReady()`** – The token provider switches to waiting `maxErrorTokenRefreshDelayMsec` milliseconds between attempts, and continues trying to retrieve the token. 
+ **Background refresh** – The token provider switches to waiting `maxErrorTokenRefreshDelayMsec` milliseconds between attempts, and continues trying to retrieve the token. 
+ **On-demand `getToken()` calls, when background refresh is disabled** – The token provider stops trying to retrieve a token and returns the previous token value, or a null value if there is no previous token. 

## Token retrieval retry scenarios
<a name="waf-mobile-sdk-how-token-retrieval-retry-scenarios"></a>

When the token provider tries to retrieve a token, it might result in auto-retries depending on where token retrieval fails in the token acquisition flow. This section lists the possible places where you might see an auto-retry.
+ **Obtaining or verifying the AWS WAF Challenge through /inputs or /verify:**
  + When a request to obtain and verify a AWS WAF challenge is made and fails, it can result in an auto-retry.
  + You might observe auto-retries happening here along with a `socketTimeoutException` error. This can have multiple causes including:
    + Low network bandwidth: Confirm your network connectivity settings
    + Mutated Application Integration URL: Confirm that the integration URL is not modified from what appears on the AWS WAF console
  + The auto-retry count is configurable with the `maxRetryCount()` function
+ **Refreshing the token:**
  + When a request to refresh the token is made through the token handler, it might result in an auto-retry.
  + The auto-retry count here is configurable with the `maxRetryCount()` function.

A configuration with no auto-retries is possible by setting `maxRetryCount(0)`.

## Token immunity time and background refresh
<a name="waf-mobile-sdk-how-token-immunity"></a>

The token immunity time that you configure in the Web ACL is independent of the token refresh interval you set in the AWS WAF mobile SDK. When you enable background refresh, the SDK refreshes the token at the interval you specify using `tokenRefreshDelaySec()`. This can result in multiple valid tokens existing simultaneously, depending on your configured immunity time.

To prevent multiple valid tokens, you can disable background refresh and use the `getToken()` function to manage the token lifecycle in your mobile app.

## Retrieving a token following app inactivity
<a name="waf-mobile-sdk-how-back-from-inactive"></a>

Background refresh is only performed while your app is considered active for your app type: 
+ **iOS** – Background refresh is performed when the app is in the foreground.
+ **Android** – Background refresh is performed when the app isn't closed, whether it's in the foreground or background.

If your app remains in any state that doesn’t support background refresh for longer than your configured `tokenRefreshDelaySec` seconds, the token provider pauses background refresh. For example, for an iOS app, if `tokenRefreshDelaySec` is 300 and the app closes or goes into the background for more than 300 seconds, the token provider stops refreshing the token. When the app returns to an active state, the token provider automatically restarts background refresh. 

When your app comes back to an active state, call `onTokenReady()` so you can be notified when the token provider has retrieved and cached a new token. Don't just call `getToken()`, because the cache might not yet contain a current, valid token. 

## Application Integration URL
<a name="waf-mobile-sdk-application-integration-url"></a>

The AWS WAF mobile SDK application integration URL points to a Web ACL that you've enabled for application integration. This URL routes requests to the correct backend server and associates them with your customer. It doesn't serve as a hard security control, so exposing an integration URL doesn't pose a security risk.

You can technically modify the provided integration URL and still obtain a token. However, we don't recommend this because you might lose visibility into challenge solve rates or encounter token retrieval failures with `socketTimeoutException` errors.

## Dependencies
<a name="waf-mobile-sdk-dependencies"></a>

Each downloadable AWS WAF mobile SDK includes a README file that lists out the dependencies for its specific version of the SDK. Refer to the README for the dependencies for your version of the mobile SDK.

## Obfuscation/ProGuard (Android SDK Only)
<a name="waf-mobile-sdk-obfuscation"></a>

If you use an obfuscation or minification product like ProGuard, you might need to exclude certain namespaces to ensure the mobile SDK works correctly. Check the README for your version of the mobile SDK to find the list of namespaces and exclusion rules.

# Code examples for the AWS WAF mobile SDK
<a name="waf-mobile-sdk-coding-examples"></a>

This section provides code examples for using the mobile SDK. 

## Initializing the token provider and getting tokens
<a name="waf-mobile-sdk-coding-basic"></a>

You initiate your token provider instance using a configuration object. Then you can retrieve tokens using the available operations. The following shows the basic components of the required code.

------
#### [ iOS ]

```
let url: URL = URL(string: "protection pack (web ACL) integration URL")!
let configuration = WAFConfiguration(applicationIntegrationUrl: url, domainName: "Domain name")
let tokenProvider = WAFTokenProvider(configuration)

//onTokenReady can be add as an observer for UIApplication.willEnterForegroundNotification
self.tokenProvider.onTokenReady() { token, error in
	if let token = token {
	//token available
	}

	if let error = error {
	//error occurred after exhausting all retries
	}
}

//getToken()
let token = tokenProvider.getToken()
```

------
#### [ Android ]

Java example:

```
String applicationIntegrationURL = "protection pack (web ACL) integration URL";
//Or
URL applicationIntegrationURL = new URL("protection pack (web ACL) integration URL");

String domainName = "Domain name";

WAFConfiguration configuration = WAFConfiguration.builder().applicationIntegrationURL(applicationIntegrationURL).domainName(domainName).build();
WAFTokenProvider tokenProvider = new WAFTokenProvider(Application context, configuration);

// implement a token result callback
WAFTokenResultCallback callback = (wafToken, error) -> {
	if (wafToken != null) {
	// token available
	} else {  
	// error occurred in token refresh  
	}
};

// Add this callback to application creation or activity creation where token will be used
tokenProvider.onTokenReady(callback);

// Once you have token in token result callback
// if background refresh is enabled you can call getToken() from same tokenprovider object
// if background refresh is disabled you can directly call getToken()(blocking call) for new token
WAFToken token = tokenProvider.getToken();
```

Kotlin example:

```
import com.amazonaws.waf.mobilesdk.token.WAFConfiguration
import com.amazonaws.waf.mobilesdk.token.WAFTokenProvider

private lateinit var wafConfiguration: WAFConfiguration
private lateinit var wafTokenProvider: WAFTokenProvider

private val WAF_INTEGRATION_URL = "protection pack (web ACL) integration URL"
private val WAF_DOMAIN_NAME = "Domain name"

fun initWaf() {
	// Initialize the tokenprovider instance
	val applicationIntegrationURL = URL(WAF_INTEGRATION_URL)
	wafConfiguration =
		WAFConfiguration.builder().applicationIntegrationURL(applicationIntegrationURL)
			.domainName(WAF_DOMAIN_NAME).backgroundRefreshEnabled(true).build()
	wafTokenProvider = WAFTokenProvider(getApplication(), wafConfiguration)
	
		// getToken from tokenprovider object
		println("WAF: "+ wafTokenProvider.token.value)
	
		// implement callback for where token will be used
		wafTokenProvider.onTokenReady {
			wafToken, sdkError ->
		run {
			println("WAF Token:" + wafToken.value)
		}
	}
}
```

------

## Allowing the SDK to provide the token cookie in your HTTP requests
<a name="waf-mobile-sdk-coding-auto-token-cookie"></a>

If `setTokenCookie` is `TRUE`, the token provider includes the token cookie for you in your web requests to all locations under the path that's specified in `tokenCookiePath`. By default,`setTokenCookie` is `TRUE` and `tokenCookiePath` is `/`. 

You can narrow the scope of the requests that include a token cookie by specifying the token cookie path, for example, `/web/login`. If you do this, check that your AWS WAF rules don't inspect for tokens in the requests that you send to other paths. When you use the `AWSManagedRulesACFPRuleSet` rule group, you configure the account registration and creation paths, and the rule group checks for tokens in requests that are sent to those paths. For more information, see [Adding the ACFP managed rule group to your web ACL](waf-acfp-rg-using.md). Similarly, when you use the `AWSManagedRulesATPRuleSet` rule group, you configure the login path, and the rule group checks for tokens in requests that are sent to that path. For more information, see [Adding the ATP managed rule group to your protection pack (web ACL)](waf-atp-rg-using.md). 

------
#### [ iOS ]

When `setTokenCookie` is `TRUE`, the token provider stores the AWS WAF token in a `HTTPCookieStorage.shared` and automatically includes the cookie in requests to the domain that you specified in `WAFConfiguration`.

```
let request = URLRequest(url: URL(string: domainEndpointUrl)!)
//The token cookie is set automatically as cookie header
let task = URLSession.shared.dataTask(with: request) { data, urlResponse, error  in
}.resume()
```

------
#### [ Android ]

When `setTokenCookie` is `TRUE`, the token provider stores the AWS WAF token in a `CookieHandler` instance that's shared application wide. The token provider automatically includes the cookie in requests to the domain that you specified in `WAFConfiguration`.

Java example:

```
URL url = new URL("Domain name");
//The token cookie is set automatically as cookie header
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
connection.getResponseCode();
```

Kotlin example:

```
val url = URL("Domain name")
//The token cookie is set automatically as cookie header
val connection = (url.openConnection() as HttpsURLConnection)
connection.responseCode
```

If you already have the `CookieHandler` default instance initialized, the token provider will use it to manage cookies. If not, the token provider will initialize a new `CookieManager` instance with the AWS WAF token and `CookiePolicy.ACCEPT_ORIGINAL_SERVER` and then set this new instance as the default instance in `CookieHandler`.

The following code shows how the SDK initializes the cookie manager and cookie handler when they aren't available in your app. 

Java example:

```
CookieManager cookieManager = (CookieManager) CookieHandler.getDefault();
if (cookieManager == null) {
	// Cookie manager is initialized with CookiePolicy.ACCEPT_ORIGINAL_SERVER
	cookieManager = new CookieManager();
	CookieHandler.setDefault(cookieManager);
}
```

Kotlin example:

```
var cookieManager = CookieHandler.getDefault() as? CookieManager
if (cookieManager == null) {
	// Cookie manager is initialized with CookiePolicy.ACCEPT_ORIGINAL_SERVER
	cookieManager = CookieManager()
	CookieHandler.setDefault(cookieManager)
}
```

------

## Manually providing the token cookie in your HTTP requests
<a name="waf-mobile-sdk-coding-manual-token-cookie"></a>

If you set `setTokenCookie` to `FALSE`, then you need to provide the token cookie manually, as a Cookie HTTP request header, in your requests to your protected endpoint. The following code shows how to do this.

------
#### [ iOS ]

```
var request = URLRequest(url: wafProtectedEndpoint)
request.setValue("aws-waf-token=token from token provider", forHTTPHeaderField: "Cookie")
request.httpShouldHandleCookies = true
URLSession.shared.dataTask(with: request) { data, response, error in }
```

------
#### [ Android ]

Java example:

```
URL url = new URL("Domain name");
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
String wafTokenCookie = "aws-waf-token=token from token provider";
connection.setRequestProperty("Cookie", wafTokenCookie);
connection.getInputStream();
```

Kotlin example:

```
val url = URL("Domain name")
val connection = (url.openConnection() as HttpsURLConnection)
val wafTokenCookie = "aws-waf-token=token from token provider"
connection.setRequestProperty("Cookie", wafTokenCookie)
connection.inputStream
```

------