Generate PKCE parameters

by unhurried

HTML

<html>
  <head>
    <script src="https://cdn.jsdelivr.net/npm/[email protected]/crypto-js.js"></script>
  </head>
  <body>
    <p>code_verifier:<br><span id="code_verifier"></span></p>  
    <p>code_challenge:<br><span id="code_challenge"></span></p>  
  </body>
</html>

JavaScript

function generateCodeVerifier() {
  if(window.crypto) {
    return generateCodeVerifierWithCrypto();
  } else {
    return generateCodeVerifierWithMath();
  }
}
function generateCodeVerifierWithCrypto() {
  let byteArray = new Uint8Array(96);
  window.crypto.getRandomValues(byteArray);
  const base64String = btoa(String.fromCharCode.apply(null, byteArray));
  const base64UrlString = base64String.replace(/\+/g, '-').replace(/\//g, '_').replace(/=/g, '');
  return base64UrlString;
}
function generateCodeVerifierWithMath() {
  let textBuffer = "";
  const availableChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-._~";
  for (var i=0; i<128; i++) {
    textBuffer += availableChars.charAt(Math.floor(Math.random() * availableChars.length));
  }
  return textBuffer;
}
function generateCodeChallenge(code_verifier) {
  const base64String = CryptoJS.SHA256(code_verifier).toString(CryptoJS.enc.Base64);
  const base64UrlString = base64String.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
  return base64UrlString;
}

const codeVerifier = generateCodeVerifier();
document.getElementById('code_verifier').innerText = codeVerifier;

const codeChallenge = generateCodeChallenge(codeVerifier);
document.getElementById('code_challenge').innerText = codeChallenge;