

**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). 

# 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).