Verify JWT with modulus and exponent (PHP)

JWT is the token format for id token published by OpenID Connect provider (Facebook, Twitter, Google, etc) or access token published by Azure Active Directory. (See here for JWT format. Id token must be JWT, but access token is no defined format in specification.)
Here I show you PHP sample code for JWT verification (validation) with modulus (n) and exponent (e).

I used Crypt_RSA package on phpseclib, and as I described here, you can run this package only with your web browser (with no software installation on your desktop) by using Azure App Service. You can also test with no extra cost !

<?php
include('Crypt/RSA.php');

// decode JWT (here, id token)
$id_token = 'eyJ0eXAiOiJKV1...';
$token_arr = explode('.', $id_token);
$headers_enc = $token_arr[0];
$claims_enc = $token_arr[1];
$sig_enc = $token_arr[2];
$sig = base64_url_decode($sig_enc);

// create Crypt_RSA
$rsa = new Crypt_RSA();

// load public key with modulus and exponent
$modulus = 'tVKUtcx_n9rt5a...';
$exponent = 'AQAB';
$public = [
  'n' => new Math_BigInteger(base64_url_decode($modulus), 256),
  'e' => new Math_BigInteger(base64_url_decode($exponent), 256),
];
$rsa->loadKey($public);

// set hash algorithm
$rsa->setHash('sha256');
$rsa->setSignatureMode(CRYPT_RSA_SIGNATURE_PKCS1);
$hash = new Crypt_Hash('sha256');

// verify !
echo $rsa->verify($headers_enc . '.' . $claims_enc, $sig) ? 'verified' : 'not verified';

function base64_url_decode($arg) {
  $res = $arg;
  $res = str_replace('-', '+', $res);
  $res = str_replace('_', '/', $res);
  switch (strlen($res) % 4) {
    case 0:
      break;
    case 2:
      $res .= "==";
      break;
    case 3:
      $res .= "=";
      break;
    default:
      break;
  }
  $res = base64_decode($res);
  return $res;
}
?>

 

Advertisements