PKCE code_verifier mismatch in SPA auth flow

Trying to get Authorization Code flow with PKCE working in a pure C# SPA wrapper. I generate the code_verifier and code_challenge correctly, but the token endpoint returns 400 Bad Request saying the verifier is invalid. Here is the POST body I am sending to /oauth/token. The code_challenge_method is S256 and I am using SHA256 hash with base64url encoding. Why is the verifier failing verification?

Check the Base64 encoding. C# Convert.ToBase64String adds +, /, and = which breaks PKCE. You need URL-safe Base64.

string ToBase64Url(byte[] data) => Convert.ToBase64String(data).TrimEnd('=').Replace('+', '-').Replace('/', '_');