Get started

Threat lab

One runnable script demonstrates the resource-server defenses described in these docs. A single process acts as the Authority, the protected resource server, and the attacker. It owns the signing key, mints tokens, serves a JWKS, runs a FastAPI application protected by auth51-verifier, and submits each attack to confirm that the verifier produces the expected result.

Run it

# in the auth51-verifier repo
python -m venv .venv && . .venv/bin/activate
pip install -e . -r examples/threat-lab/requirements.txt
python examples/threat-lab/lab.py

A means that an attack was blocked or that the legitimate baseline request was allowed. A means that the expected defense failed. The process exits with a non-zero status if any check fails, so the lab also serves as a conformance test.

What it demonstrates

#AttackDefense that stops it
Legit call: valid token + valid DPoPAllowed (the baseline)
1Steal a token and replay it without proofProof-of-possession: a cnf-bound token requires a DPoP proof (RFC 9449); copying the token does not provide the key
2Forge a DPoP proof with the attacker’s keyThe proof key must equal the token’s cnf.jkt (thumbprint mismatch)
3Request with an inflated scopeThe token must carry the scope required by the endpoint
4Wrong operation (O6): use a GET token on DELETEEach endpoint derives its own a51:rs scope. A GET token lacks the DELETE scope, while a correctly scoped DELETE token is allowed
5Replay a DPoP proof on a different requesthtu binds the proof to this exact URL
6Present an expired tokenThe exp claim, including the permitted clock skew
7Forge a token with the attacker’s signing keyJWKS signature verification
8Use a token at the wrong resource serveraud (audience)
9Tamper the agent’s prompt or codeThe identity checksum changes, so the Authority won’t mint under the registered identity

The verifier blocks attacks 1–8 at the resource server level without calling the Authority. Attack 9 exercises the token minting-side identity check: agent identity is derived from the agent rather than from a stored secret, so tampering changes the checksum before a token is issued.

Note

The lab installs its public key in the verifier’s JWKS cache because it acts as the Authority for the test. The unmodified verifier checks the signature, DPoP proof, scope, audience, and expiry; the security checks are not stubbed. Replacing the local mint with a token from authority.auth51.com exercises the same verifier path.