Configures authenticated DAST sessions in ZAP - ZAP Context + Authentication Method (form, JSON, script, browser-based, HTTP/NTLM), Session Management strategy (cookie, header, script), Verification Strategy (regex indicators, poll-URL), CSRF token handling, OAuth/bearer header injection, logged-in/logged-out indicator calibration, and context XML export for use with `-n` in baseline and full scans. Use when the team needs DAST coverage of authenticated routes - the most common DAST gap and the hardest DAST setup to get right.
74
93%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
View guide
Low
Low-risk findings worth noting
Unauthenticated DAST scans cover only the public attack surface. For most apps, 70-90% of routes sit behind a login wall. This skill is a build-an-X workflow that walks the full authenticated session setup: ZAP Context creation, choosing the right Authentication Method, wiring Session Management, calibrating logged-in/out indicators, handling CSRF tokens, injecting OAuth/bearer headers, and exporting the context file for CI reuse.
Nearest neighbors and differentiation axes:
zap-baseline covers the -n context_file
flag but not how to build that file.dast-scan-cadence-author covers cadence
(PR-blocking vs. nightly vs. release), not auth wiring./logout, so
the scanner does not log itself out mid-scan (Step 1).-config or env vars
rather than hardcoding them (Step 10)..zap/context.xml (Step 11).-n context.xml, or replay the same session in Burp
for manual testing (Steps 11-12).Per zaproxy.org/docs/desktop/start/features/authentication/, authentication in ZAP is always scoped to a Context - a named set of URLs. Create one before touching any auth setting:
Session Properties > Contexts > Add.myapp-auth).https://app.example.com/.*https://app.example.com/logout.*All auth settings attach to this Context. CLI scans reference it via
-n context.xml (Step 9).
Per zaproxy.org/docs/desktop/start/features/authmethods/, ZAP supports five built-in methods. Choose by app login mechanism:
| App login type | Method to use |
|---|---|
| HTML form POST with username + password fields | Form-Based |
JSON POST {"username":"...","password":"..."} | JSON-Based |
| HTTP Basic / Digest / NTLM challenge | HTTP/NTLM |
| Custom flow (OTP, magic link, multi-step) | Script-Based |
| Modern browser-rendered SSO / OAuth redirect | Browser-Based (auth-helper addon) |
Per zap-methods, Form-Based auth requires:
https://app.example.com/login)username={%username%}&password={%password%}
ZAP replaces {%username%} / {%password%} with User credentials at
scan time. Never hardcode credentials in this field.name
attributes).Per zap-methods, Form-Based auth supports re-authentication - ZAP detects session expiry and re-logs in automatically mid-scan.
CSRF token handling for form login: if the login form contains an anti-CSRF
token field, configure its name in Tools > Options > Anti CSRF Tokens
(per zap-auth). ZAP fetches the login page, extracts the token,
and replays it with the POST automatically.
Per zap-methods, JSON-Based auth is for apps whose login endpoint accepts a JSON body rather than form-encoded params:
{"username":"{%username%}","password":"{%password%}"}ZAP sends Content-Type: application/json automatically. Supports
re-authentication. Use this for REST API login endpoints returning a
session cookie or JWT response body.
Per zap-methods, Script-Based auth handles flows that
Form-Based and JSON-Based cannot: OTP-augmented logins, multi-step forms,
OAuth authorization-code flows with PKCE, or apps that rotate CSRF seeds on
every page load. It requires the Script Console add-on and an Authentication
script that builds the login request via helper.prepareMessage().
See references/script-based-auth.md for the
Script Console setup, the Groovy authenticate() skeleton, and the OAuth
authorization-code exchange pattern.
Per zaproxy.org/docs/desktop/addons/authentication-helper/, the Authentication Helper add-on provides Browser-Based Authentication for apps that use JS-rendered login pages, SSO redirects, or WebAuthn flows that headless HTTP clients cannot replay:
authentication:
method: "browser"
parameters:
loginPageUrl: "https://app.example.com/login"
verification:
method: "autodetect"
sessionManagement:
method: "autodetect"ZAP launches Firefox, navigates to loginPageUrl, fills the username and
password fields, and captures the resulting session token. The
autodetect verification asks ZAP to find a suitable verification URL
automatically.
Per zaproxy.org/docs/desktop/start/features/sessionmanagement/,
ZAP supports three session management methods. Set in
Session Properties > Context > Session Management:
| App session type | Method |
|---|---|
Session ID in a cookie (JSESSIONID, session, etc.) | Cookie-Based Session Management |
Authorization header (Basic, JWT Bearer) | HTTP Authentication Session Management |
| Custom header or token rotation | Script-Based Session Management |
Per zap-session, Cookie-Based "session is being tracked through cookies" and tokens are imported from the HTTP Sessions Extension.
Per zap-session, Script-Based "is called whenever session management actions are performed" and requires the Scripts Console add-on.
Per zap-auth, ZAP exposes environment variables
(ZAP_AUTH_HEADER_VALUE, ZAP_AUTH_HEADER, ZAP_AUTH_HEADER_SITE) for
header-based injection of pre-obtained bearer tokens - OAuth client-credentials,
API keys, CI-issued JWTs. Set them in the CI environment before the scan. For a
full authorization-code exchange, use Script-Based auth (Step 5) instead and let
ZAP manage token refresh.
See references/oauth-bearer-injection.md for the variable table and the CI Docker example.
Per zap-verify, ZAP uses an Authentication Verification Strategy to know whether a request runs as an authenticated user, driven by a Logged-In Indicator and a Logged-Out Indicator regex. Four strategies exist (Check Every Response, Check Every Request, Check Every Request or Response, Poll the Specified URL); calibrate the indicators by flagging logged-in and logged-out responses in the History tab.
See references/verification-strategy.md for the indicator examples, the strategy-selection table, and the calibration steps.
Per zaproxy.org/docs/desktop/start/features/users/, users are
configured per-context at Session Properties > Context > Users > Add.
Each user stores credentials that map to the Authentication Method's
{%username%} / {%password%} placeholders.
Per zap-users: "Authentication Methods define the process; Users store the specific credentials needed for each user account." One context can hold multiple users (admin, read-only, unauthenticated) to test privilege separation in a single scan.
Never store plaintext credentials in the exported context XML committed to
version control. Reference environment variables in CI (Step 8 pattern) or
use ZAP's -config CLI flag to inject credentials at scan time:
zap-full-scan.py -t https://app.example.com \
-n /zap/wrk/context.xml \
-config context.users\(0\).name=scanner \
-config context.users\(0\).credentials.username=$ZAP_USER \
-config context.users\(0\).credentials.password=$ZAP_PASSOnce auth is confirmed working via the Authentication Tester (per
zap-helper, under Tools > Authentication Tester or
Ctrl+T), export the Context:
File > Export Context > save as context.xml
Commit context.xml to the repo at .zap/context.xml. The file encodes
auth method, session management strategy, verification strategy, and
include/exclude URL patterns. It does NOT contain user credentials when
users are configured with the -config override pattern above.
Use in CI:
docker run --rm \
-e ZAP_AUTH_USERNAME=$ZAP_USER \
-e ZAP_AUTH_PASSWORD=$ZAP_PASS \
-v $(pwd):/zap/wrk/:rw \
ghcr.io/zaproxy/zaproxy:stable \
zap-baseline.py -t https://app.example.com -n /zap/wrk/.zap/context.xml -J report.jsonPer zap-baseline, the -n CONTEXT_FILE flag loads
this file and activates authentication for the scan.
For apps already configured in ZAP, mirror the session in Burp for manual testing by capturing a valid authenticated request via ZAP proxy, then:
Save as HAR.Proxy > HTTP history > Import HAR.Project > Session handling rules > Macros) that
replays the login POST and extracts the session token using a regex
matching the cookie or JSON access_token field.Settings > Sessions > Session handling rules > Add) with scope covering the entire app and the macro set as the
rule action.This keeps Burp and ZAP scanning the same authenticated surface without re-configuring login from scratch in each tool.
A team needs authenticated DAST coverage of a form-login SPA at
app.example.com whose login page carries an anti-CSRF token.
myapp-auth including https://app.example.com/.*
and excluding https://app.example.com/logout.* (Step 1).username={%username%}&password={%password%} and register the CSRF field
name under Tools > Options > Anti CSRF Tokens (Steps 2-3).JSESSIONID cookie, so they set Cookie-Based Session
Management (Step 7).href="/logout" and a logged-out
Please log in page as indicators, using Check Every Response (Step 9,
references/verification-strategy.md).scanner user and export the Context to .zap/context.xml, with
credentials supplied at scan time via -config (Steps 10-11).zap-baseline.py -t https://app.example.com -n /zap/wrk/.zap/context.xml -J report.json.Result: the baseline scan authenticates, re-logs in when the session expires, and reports vulnerabilities across the routes behind the login wall instead of only the public pages.
| Anti-pattern | Why it fails | Fix |
|---|---|---|
Skip context creation, use -u user:pass flag | No re-auth; spider logs out mid-scan | Context + auth method (Steps 1-3) |
| Hardcode credentials in context.xml | Secrets leak in version control | -config injection or env vars (Step 10) |
| No logged-out indicator | ZAP reports false coverage on expired sessions | Calibrate both indicators (Step 9) |
| Form-based auth on a JSON-API login | ZAP sends form-encoded body; app rejects it | JSON-based auth (Step 4) |
Exclude /login from context scope | Auth POST never proxied; ZAP can't authenticate | Include login URL; exclude only /logout (Step 1) |
| Browser-based auth without auth-helper addon | method: browser is not a built-in; scan fails | Install Authentication Helper from Marketplace (Step 6) |
| Set verification strategy but no indicators | Strategy is inactive; ZAP never detects re-auth need | Supply at least one logged-in regex (Step 9) |
-config flag injection pattern; anyone needing credentials
must supply them separately.zap-baseline - baseline scan using the context file produced heredast-scan-cadence-author - layered DAST cadence (baseline, full, Burp deep)