Yes! I got it! Your advice with Postman helped me see the error clearly. It turns out my code_verifier was incorrectly formed - it was too long.
Ultimately, the real issue was in what types are returned in node’s crypto package (as a Buffer) and expo’s crypto package (expo-crypto) (as a Uint8Array). I had to import the Buffer package and encode it to Base64 directly (using node’s encode package for Base64 encoding didn’t work for me)
The correct way to produce the code_verifier and code_challenge as specified by auth0 using expo packages is as follows:
import * as Crypto from 'expo-crypto';
import * as Random from 'expo-random';
import { Buffer } from 'buffer';
function URLEncode(str) {
return str
.replace(/\+/g, '-')
.replace(/\//g, '_')
.replace(/=/g, '');
}
async function sha256(buffer) {
return await Crypto.digestStringAsync(
Crypto.CryptoDigestAlgorithm.SHA256,
buffer,
{ encoding: Crypto.CryptoEncoding.BASE64 }
);
}
const randomBytes = await Random.getRandomBytesAsync(32);
const base64String = Buffer.from(randomBytes).toString('base64');
const code_verifier = URLEncode(base64String);
const code_challenge = URLEncode(await sha256(code_verifier));
(DON’T try and include the node crypto package as it’s deprecated) I hope this will prove useful to anyone else who finds this post!
If anyone is interested, I wrote a more detailed write up on these issues on my blog: