ZAP Verification Methods — How They Work
1. autodetect
ZAP passively observes traffic during and after login to figure out verification on its own.
What ZAP looks for:
- A URL that returns different responses when logged in vs logged out
- Session tokens appearing in responses (Authorization header, Set-Cookie, JSON body)
- Pages that redirect differently based on auth state
How it decides:
ZAP sends login request
→ Watches response for session tokens (JWT, cookie, header)
→ Makes a few requests to discovered URLs
→ Compares responses before/after login
→ Picks a URL where the response changes most significantly
→ Uses that as the verification URL going forward
Works well when:
- MPA/server-rendered apps — login sets a cookie, pages return different HTML
- Simple SPAs where login returns a clear JWT in response body
- Apps like Juice Shop where
/rest/user/loginreturns JWT directly in JSON → ZAP detects the Authorization header being set and uses it as the success signal
Fails when:
- SPA shell HTML looks identical logged-in vs logged-out
- Backend API is on a different domain than the login page
- Login flow involves redirects through multiple domains (SSO/OAuth)
- Session token is stored in memory/localStorage, not visible in headers
2. response
ZAP checks the HTTP response of the login request URL itself using a regex you provide.
How it works:
ZAP sends login request to loginRequestUrl
→ Gets the response back
→ Runs loggedInRegex against response body
→ If regex matches → logged in ✅
→ If regex doesn't match → logged out ❌
→ Re-runs this check periodically during scan to detect session expiry
Example config:
verification:
method: response
loggedInRegex: '\Q"token"\E'
loggedOutRegex: 'Unauthorized|invalid credentials'
Works well when:
- JSON auth — loginRequestUrl is an explicit backend API endpoint
- Login response body contains a clear success/failure indicator
- e.g.
/gateway/users/loginreturns{"token": "..."}on success
Fails when:
- Browser auth — there is no single "login response" to inspect
- SPA where login response is the same HTML shell regardless of outcome
- Login goes through redirects before final response
- Backend URL is different domain and ZAP loses track of the response
3. poll
ZAP periodically hits a URL you specify and checks its response against a regex to confirm session is still active.
How it works:
ZAP logs in (via json or browser)
→ Every N seconds, ZAP hits pollUrl
→ Attaches current session token to the request
→ Runs loggedInRegex against response
→ If matches → session valid, continue scan ✅
→ If doesn't match → session expired, re-login and retry ❌
Example config:
verification:
method: poll
pollUrl: https://api.example.com/gateway/users/profile
pollFrequency: 60
loggedInRegex: '\Q"email"\E'
loggedOutRegex: 'Unauthorized|401'
Works well when:
- SPA with browser auth — you explicitly point ZAP at a protected API endpoint
- Any app where you know a reliable protected URL that returns 401 when unauthed
- Long scans where session tokens expire and ZAP needs to re-authenticate
Fails when:
- pollUrl is wrong or unreachable
- loggedInRegex doesn't match the actual response body
- Session token is not being attached to the poll request (common with browser auth + autodetect session management)
- Poll URL is on the frontend domain (SPA shell) instead of backend API
Quick Comparison
┌─────────────┬──────────────────────────────┬─────────────────────────────┐
│ Method │ What ZAP checks │ Best for │
├─────────────┼──────────────────────────────┼─────────────────────────────┤
│ autodetect │ Observes traffic passively, │ MPA, simple apps, │
│ │ picks its own URL + signal │ Juice Shop style APIs │
├─────────────┼──────────────────────────────┼─────────────────────────────┤
│ response │ Login request response body │ JSON auth with explicit │
│ │ matched against your regex │ backend loginRequestUrl │
├─────────────┼──────────────────────────────┼─────────────────────────────┤
│ poll │ Separate protected URL hit │ SPA + browser auth, │
│ │ periodically with regex │ any app with known API │
└─────────────┴──────────────────────────────┴─────────────────────────────┘
Decision Rule
Is it an SPA?
Yes + JSON auth → response (you know the backend login URL)
Yes + Browser auth → poll (autodetect sees identical HTML shell)
Is it an MPA / server-rendered?
Any auth method → autodetect works fine
Do you have a reliable protected API endpoint?
Always → poll is the most explicit and reliable option
Why "Verification URL identified: true" ≠ Success
For poll and autodetect, ZAP reports two things independently:
"Verification URL identified: true"
→ ZAP found/reached the URL ✅
→ Says nothing about whether the regex matched
"Authentication failed"
→ The regex did not match the response ❌
→ OR the login itself never completed
Both can be true at the same time:
ZAP reached your pollUrl just fine,
but your loggedInRegex didn't match the response body.