A confidential server-side web app already authenticates to the token endpoint with a client secret, and a reviewer asks why it should also use PKCE. Explain exactly what PKCE sends at each step, what an attacker who captures the authorization code can and cannot do with and without it, and what `state` protects that PKCE does not.
At the start of the flow the client generates a random code_verifier, keeps it, and sends only a code_challenge: the SHA-256 of the verifier, base64url-encoded (S256). The authorization server stores the challenge with the code it issues. When the client redeems the code at the token endpoint, it sends the verifier; the server hashes it and compares. The code travels through the browser (a redirect URL, so history, logs, referrers), but the verifier never does: it goes only over the direct back-channel call. Someone who captures the code cannot produce a verifier that hashes to the challenge, so the code is useless to them. A client secret does not replace that: it proves the token request comes from the registered client, not that this particular code belongs to this particular flow. state is a different defence: it ties the redirect back to a login the client actually started, which is CSRF protection for the login itself.