Skip to content

How do I troubleshoot AWS WAF JavaScript integration issues?

6 minute read
1

I want to troubleshoot errors with the AWS WAF JavaScript integration on my website.

Resolution

The AWS WAF JavaScript integration provides client-side challenge or CAPTCHA verification on your web application. If tokens don't send in cross-domain requests, challenge scripts don't load, tokens expire, or single-page application (SPA) isn't compatible, then you experience an issue.

To resolve these issues, confirm that your integration script loads correctly. Then, make sure that you correctly configured the token cookie domain, and check that your application handles token refreshes.

Resolve token not sent with cross-domain requests

AWS WAF scopes the aws-waf-token cookie to the domain that served the challenge script. If your frontend and backend APIs are on different subdomains, then the browser doesn't include the token cookie in cross-origin requests. AWS WAF then returns an "HTTP 403 Forbidden" response.

Set the cookie domain to the apex domain

To configure the token domain list in the AWS WAF console, complete the following steps:

  1. Open the AWS WAF console and choose your web access control list (web ACL).
  2. Choose Manage details.
  3. Under Token domains, add your apex domain and all other applicable domains that your application uses.
  4. Choose Save.
  5. Copy the JavaScript integration snippet from the Application integration tab. The snippet automatically includes the awsWafCookieDomainList with your configured domain.

If you need to set the domain dynamically, for example, multi-tenant applications, then add the following code before you load the AWS WAF challenge script:

<script>
  window.awsWafCookieDomainList = ['.example.com'];
</script>
<script src="https://<integration-URL>/challenge.js" defer></script>

Note: Replace .example.com with your apex domain to set the token cookie with a domain attribute that's shared across all your subdomains.

Use AwsWafIntegration.fetch() for cross-domain API calls

As an alternative to configuring the cookie domain, use the AWS WAF fetch wrapper to attach the token as a request header:

const response = await AwsWafIntegration.fetch(
  "https://api.example.com/resource",
  { method: "POST", body: JSON.stringify(payload) }
);

Note: AwsWafIntegration.fetch() attaches the token as a request header. This bypasses cookie domain restrictions entirely.

Fix challenge script that fails to load or initialize

The challenge script might fail to load if a Content Security Policy (CSP) blocks the external script domain or if the integration URL is incorrect.

To identify why the challenge script fails to load, complete the following steps:

  1. Open browser developer tools.
  2. Check the Console and Network tabs for blocked script errors.
  3. Verify that your Content-Security-Policy header includes the AWS WAF integration URL in the script-src directive.
  4. Confirm that the integration URL matches the one generated in the AWS WAF console under the Application integration tab for your web ACL.
  5. Check that connect-src also allows the AWS WAF token endpoint domain.

The following example shows a Content Security Policy (CSP) header that allows the AWS WAF challenge script and token endpoint:

`Content-Security-Policy: script-src 'self' https://INTEGRATION-URL.token.awswaf.com;   connect-src 'self' https://INTEGRATION-URL.token.awswaf.com;`

Note: Replace INTEGRATION-URL with the integration URL generated in the AWS WAF console for your web ACL. If you use a nonce-based CSP, you can't apply a nonce to the dynamically loaded AWS WAF scripts. Use the domain allowlist approach instead.

Address token expiration in long user sessions

AWS WAF tokens have a configurable immunity time that defaults to 5 minutes. If users stay on the same page in your application for extended periods, then the token can expire before the next request. You might then receive an "HTTP 403 Forbidden" response or a new error response code.

Implement automatic token refresh

To refresh the token before each API request, use the following JavaScript function that calls AwsWafIntegration.getToken() before the fetch.

async function refreshAndFetch(url, options) {
  await AwsWafIntegration.getToken();
  return AwsWafIntegration.fetch(url, options);
}

Increase token immunity time

To increase the immunity time for your challenge or CAPTCHA rule action, complete the following steps:

  1. Open the AWS WAF console.
  2. Select your web ACL.
  3. Choose Manage details.
  4. Under Protection pack (web ACL) behavior, find Default immunity time.
  5. Edit the rule that applies the Challenge or CAPTCHA action.
  6. Increase the Immunity time value up to the maximum configured on the web ACL. The minimum is 60 seconds and the maximum is 259,200 seconds or 3 days.
    Note: If you increase immunity time, you then reduce security posture. Make sure that you balance the usability against bot protection requirements.

Resolve integration issues with SPAs

Single-page applications (SPAs) use client-side routing, so the page never fully reloads after the initial load. Because the page doesn't reload, the AWS WAF SDK doesn't re-execute its challenge logic when routes change. As a result, tokens become stale or expired on subsequent API calls.

Call getToken() on route changes

To refresh the token on each route change, add the following React Router hook to your application:

// React Router example
useEffect(() => {
  AwsWafIntegration.getToken();
}, [location.pathname]);

Use AwsWafIntegration.fetch() for all API calls

Replace native fetch() or XMLHttpRequest calls with AwsWafIntegration.fetch() throughout your application. This approach includes a valid, non-expired token with every request regardless of the client-side routing state.

Fix CAPTCHA or challenge puzzle that doesn't render

The CAPTCHA or challenge page might fail to render if the DOM container is missing, CSS hides the element, or JavaScript errors halt execution.

To identify why the CAPTCHA or challenge puzzle doesn't render, take the following actions:

  • Verify that the page doesn't have CSS rules that hide elements with the AWS WAF challenge container ID. For example, check that no display:none rule applies to inline frame (iframe) elements, because AWS WAF renders challenges inside iframes.
  • Check if the browser console has JavaScript errors that occur before or during the AWS WAF script initialization.
  • Confirm that no ad blockers or browser extensions block requests to the AWS WAF token domain.
  • For custom CAPTCHA integrations, confirm that the renderCaptcha() target container element exists in the DOM when the function is called.
    The following example shows a custom CAPTCHA rendering with the required DOM container element:
    <div id="waf-captcha-container"></div>
    <script>
      AwsWafCaptcha.renderCaptcha(
        document.getElementById("waf-captcha-container"),
        { apiKey: "<your-api-key>", onSuccess: (token) => { /* proceed */ } }
      );
    </script>

Resolve HTTP 405 Method Not Allowed on token fetch endpoint

If a reverse proxy or CDN modifies the HTTP method before it reaches the AWS WAF integration endpoint, then you might receive an "HTTP 405 Method Not Allowed" response code when the SDK attempts to fetch or refresh a token.

To resolve this issue, take the following actions:

  • Verify that requests to the challenge endpoint are not proxied through a layer that rewrites the HTTP method.
  • Confirm that your CDN or load balancer forwards the original request method (GET/POST) to the AWS WAF integration URL.
  • Check that Cross-Origin Resource Sharing (CORS) configuration allows GET and POST methods to the token domain.
  • If you use CloudFront, verify that the behavior matching the AWS WAF token path allows the required HTTP methods.

Related information

Client application integrations in AWS WAF

Using the intelligent threat JavaScript API

Token use in AWS WAF intelligent threat mitigation

How to use the integration fetch wrapper

How to use the integration getToken

AWS OFFICIALUpdated 25 days ago