- Newest
- Most votes
- Most comments
If report works (200) but mp_verify fails (400), your SDK is talking to AWS, but AWS is refusing to "anchor" a token to your current browser session due to domain mismatch or suspected automation.
To resolve this certainty, check these three specific technical blockers:
- Public Suffix Restriction: If testing on *.cloudfront.net, ensure window.awsWafCookieDomainList does not have a leading dot. Browsers reject cookies with a leading dot on Public Suffix List domains, causing the SDK to fail the verification handshake.
- Targeted Signal Interference: Bot Control TARGETED inspects the browser signals during the challenge. If your test environment (e.g., a scripted browser or a window without interaction) triggers a high-confidence bot signal, mp_verify will return a 400 to prevent token issuance. Set all individual rules within the BotControl group to Count (not just the group override) to see if the 400 vanishes.
- Exact Domain Match: Ensure the Origin header in the mp_verify POST exactly matches an entry in your Token domains list. Even a mismatch between www.domain.com and domain.com in the WAF configuration will trigger a 400.
In Short: The error occurs because WAF cannot map the verification request to your Web ACL due to missing domain authorization or an incorrect SDK endpoint.
The HTTP 400 "Invalid request" on mp_verify indicates a domain or endpoint mismatch. To fix it, ensure these three configurations are exact:
- Token Domains: You must explicitly add both your custom domain and the
*.cloudfront.netdomain to the Token domains list in your Web ACL settings. - Integration URL: Do not use a generic script URL. You must use the specific Application Integration URL retrieved from the WAF API (Format:
https://<id>.us-east-1.sdk.awswaf.com/<name>/challenge.js). - API Key: For TARGETED bot control, an API key is mandatory. Create it via aws wafv2 create-api-key for your specific domains and ensure it is active.
Thanks for the suggestions, they helped us find the solution!
The key issue was the token acquisition mechanism. We were trying to use the challenge.js SDK for standalone token acquisition viamp_verify, but the correct approach is to use the WAF Challenge rule action on the initial page load.
What works: A Challenge rule scoped to GET requests on our protected pages. The browser solves the challenge invisibly on page load and acquires the aws-waf-token cookie. Subsequent POST requests pass through with the token already set.
What doesn't work (for reference):
- challenge.js / jsapi.js standalone token acquisition via mp_verify, always returns 400 regardless of configuration
- Challenge rule on POST returns HTTP 202 which breaks legacy AJAX frameworks that expect a specific response format
In short: Challenge on GET (page load) = works. Challenge on POST or standalone SDK = doesn't work for our use case. No JS SDK needed.
Thanks again for pointing us in the right direction!
Thanks for the suggestions. I tested all three but the issue persists:
-
Token Domains - Already configured: token_domains = ["myapp.ninja", "d1someid.cloudfront.net"] (custom domain + CloudFront default domain).
-
Regional URL - Tested https://<id>.us-east-1.sdk.awswaf.com/<id>/<name>/challenge.js (redirects to us-east-1.token.awswaf.com). Same 400 on mp_verify. Also tested the edge.sdk.awswaf.com URL from get-web-acl API - same result.
-
API Key - Created via aws wafv2 create-api-key --scope CLOUDFRONT --token-domains myapp.ninja. Also tested with jsapi.js from the captcha-sdk.awswaf.com URL using this key - same 400.
Additional tests (all produce mp_verify 400):
- override_action { count {} } vs override_action { none {} } on TARGETED rule
- With/without a separate Challenge rule action in the Web ACL
- Single TARGETED rule only (COMMON removed from Web ACL)
- With/without window.awsWafCookieDomainList = ['.myapp.ninja']
- Real Chrome browser (not headless)
The report endpoint on the same SDK domain works fine (HTTP 200). Only mp_verify fails. The OPTIONS preflight returns Access-Control-Allow-Origin: *, but the POST 400 response has no CORS headers - the browser shows a CORS error but the real error is 400 "Invalid request".
AwsWafIntegration is defined after script load, but getToken() resolves with an undefined token.
Is there an additional setup step in the WAF console (Application Integration tab) that we might be missing? Or could this bespecific to the Web ACL configuration?
Relevant content
- asked 3 years ago
- asked 8 months ago
- asked 2 years ago
- AWS OFFICIALUpdated 10 months ago
- AWS OFFICIALUpdated 10 months ago
