redirect_uri differs between sign-in and token exchange
What it means
The token request must send the identical redirect_uri used in the authorization request.
Fix
Use one exact string in both requests (your app may be normalising it, e.g. adding a slash).
Check it with smart-doctor
Run your login and smart-doctor ranks this cause against the others, with the evidence it found.
npx smart-doctor check my-profileAlready have the server’s error? Explain it without running anything.
npx smart-doctor explain '{"error":"invalid_grant"}'