56916841b5
The PKCE cookie's payload has now needed three serialization fixes at the same spot: the original flat 'k=v;k=v' string tripped http.cookies' \073 quoted form (dropped whole by strict cookie parsers like Go's net/http — #83832 field case), and #99176 URL-encoded the whole flat payload to stay inside the RFC 6265 cookie-octet set. The stacked layers (single-encoded next=, ';' joins, whole-payload encoding, legacy discriminator) were the recurring defect source. Kill the bug class instead of patching it again: the payload is a dict end-to-end and goes on the wire as base64url(JSON) — the urlsafe alphabet is a strict subset of cookie-octets, and JSON framing means no segment value can ever collide with a delimiter. parse_pkce_payload keeps a three-rung compatibility ladder (base64url(JSON) -> oldest flat form split-as-is -> #99176 unquote-then-split) for in-flight cookies during a rolling upgrade (10-minute TTL); a new cookie hitting an old server fails the OAuth state check and the user just retries. The 'next' segment is stored as its plain validated path — no extra encoding layer, so the post-login redirect Location is byte-for-byte the original target. Refs #99176, #84065.