amazon web services - Verify JWT signature with RSA public key in PHP

933

In PHP, I'm trying to validate an AWS auth token (JWT returned from getOpenIdTokenForDeveloperIdentity) using the AWS's RSA public key (which I generated from modulus/exponent at https://cognito-identity.amazonaws.com/.well-known/jwks_uri). The key begins with the appropriate headers/footers-----BEGIN RSA PUBLIC KEY----- etc. I've looked at a few PHP libraries likeEmarref\Jwt\Jwt, however I get the error:error:0906D06C:PEM routines:PEM_read_bio:no start line. It all boils down to the basic php function:openssl_verify.

I've looked at the php.net/manual for openssl-verify, but I'm still not clear on the parameter details. The algorithm needed isRS512.

I am able to verify the JWT token using node.js with no problems (same key and token). For that I used the library: https://github.com/auth0/node-jsonwebtoken

Not sure why this doesn't work in PHP. Can I not use an RSA Public Key?

function verifyKey($public_key) {
  $jwt = new Emarref\Jwt\Jwt();

  $algorithm = new Emarref\Jwt\Algorithm\Rs512();
  $factory = new Emarref\Jwt\Encryption\Factory();
  $encryption = $factory->create($algorithm);
  $encryption->setPublicKey($public_key);
  $context = new Emarref\Jwt\Verification\Context($encryption);
  $token = $jwt->deserialize($authToken);

  try {
    $jwt->verify($token, $context);
  } catch (Emarref\Jwt\Exception\VerificationException $e) {
    debug($e->getMessage());
  }
}
20

Answer

Solution:

Could you try using another PHP library: https://github.com/Spomky-Labs/jose

// File test.php
require_once __DIR__.'/vendor/autoload.php';

use Jose\Checker\ExpirationChecker;
use Jose\Checker\IssuedAtChecker;
use Jose\Checker\NotBeforeChecker;
use Jose\Factory\KeyFactory;
use Jose\Factory\LoaderFactory;
use Jose\Factory\VerifierFactory;
use Jose\Object\JWKSet;
use Jose\Object\JWSInterface;

// We create a JWT loader.
$loader = LoaderFactory::createLoader();

// We load the input
$jwt = $loader->load($input);

if (!$jws instanceof JWSInterface) {
    die('Not a JWS');
}

// Please note that at this moment the signature and the claims are not verified

// To verify a JWS, we need a JWKSet that contains public keys (from RSA key in your case).
// We create our key object (JWK) using a RSA public key
$jwk = KeyFactory::createFromPEM('-----BEGIN RSA PUBLIC KEY-----...');

// Then we set this key in a keyset (JWKSet object)
// Be careful, the JWKSet object is immutable. When you add a key, you get a new JWKSet object.
$jwkset = new JWKSet();
$jwkset = $jwkset->addKey($jwk);


// We create our verifier object with a list of authorized signature algorithms (only 'RS512' in this example)
// We add some checkers. These checkers will verify claims or headers.
$verifier = VerifierFactory::createVerifier(
    ['RS512'],
    [
        new IssuedAtChecker(),
        new NotBeforeChecker(),
        new ExpirationChecker(),
    ]
);

$is_valid = $verifier->verify($jws, $jwkset);

// The variable $is_valid contains a boolean that indicates the signature is valid or not.
// If a claim is not verified (e.g. the JWT expired), an exception is thrown.

//Now you can use the $jws object to retreive all claims or header key/value pairs
284

Answer

Solution:

I was able to get this library to work. However I had to build the key using KeyFactory::createFromValues instead of KeyFactory::createFromPEM. THANK YOU!

People are also looking for solutions to the problem: php - Passing Variables Between Two Classes

Source

Didn't find the answer?

Our community is visited by hundreds of web development professionals every day. Ask your question and get a quick answer for free.

Ask a Question

Write quick answer

Do you know the answer to this question? Write a quick response to it. With your help, we will make our community stronger.

Similar questions

Find the answer in similar questions on our website.