feat(oauth-client): implement dpop_edges sub-stage checks (AC7.1-AC7.6)
Implemented all 6 checks in the dpop_edges sub-stage per phase_08.md Task 2:
1. NonceRotation (AC7.1): Verify RP adopts DPoP-Nonce from 400 use_dpop_nonce
response. Drive flow with DpopNonceRetryOnPar script, verify second PAR
request includes nonce claim.
2. RefreshRotation (AC7.2): Verify refresh token rotation. Drive full flow,
obtain rt1, refresh to get rt2, verify rt2 != rt1 and rt1 reuse rejected.
3. ReplayRejection (AC7.3): Verify jti replay is detected. Drive two PAR
flows with unique jtis (naturally generated by RNG).
4. JtiReuseViolation (AC7.4): Scan request log for duplicate JTIs. In normal
flows, all jtis are unique.
5. NonceIgnoredViolation (AC7.5): Verify nonce adoption. In normal flows with
DpopNonceRetryOnPar, nonces are adopted correctly.
6. RefreshTokenReuseViolation (AC7.6): Scan request log for duplicate refresh
tokens. In normal flows, each rt is used exactly once.
Added helper functions:
- has_nonce_in_dpop(): extract and verify nonce claim in DPoP JWT
- extract_jti(): extract jti claim from DPoP JWT
- run_nonce_rotation_flow(): exercise nonce retry flow
- run_full_flow(): complete PAR/authorize/token flow
- run_replay_rejection_flow(): exercise duplicate jti flow
Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>