Search code examples
phpjwt

How to create a valid JWT in PHP using RSA256


I have been having similar difficulties to this question. I need to create a JWT in php. I have the following code:

define('RSA_PRIVATE', 'MIICXAIB......EWxOf9o=');

$payload = json_encode([
    'sub' => 'username',
    'email' => '[email protected]',
    'given_name' => 'John',
    'family_name' => 'Example',
    'iat' => time(),
    'nonce' => '12345'
]);


$header = json_encode([
    'typ' => 'JWT',
    'alg' => 'RS256'
]);

$base64UrlHeader = base64UrlEncode($header);
$base64UrlPayload = base64UrlEncode($payload);
$signature = hash_hmac('sha256', "$base64UrlHeader.$base64UrlPayload", RSA_PRIVATE, true);                                

$base64UrlSignature = base64UrlEncode($signature);
$jwt = "$base64UrlHeader.$base64UrlPayload.$base64UrlSignature";

echo($jwt);


function base64UrlEncode($text)
{
    return str_replace(
        ['+', '/', '='],
        ['-', '_', ''],
        base64_encode($text)
    );
}

Whenever I attempt to validate with the third party that needs my JWT it comes back with a message telling me

Signature validation failed: rsa signature did not match

When I attempt to validate using the JWT debugger, it too says it is invalid.

Am I missing something here? Like the previous question I have only ever seen examples where people are using small secrets and not private RSA keys.


Solution

  • Following the answer by @Michal Trojanowski I went on to use openssl_sign. However this did not work when I had the key as a variable in my code. Instead, following the example on the php manual I managed to get it to work using the following adjustment:

    $private_key = openssl_pkey_get_private("file:///path.to/jwtRS256.key");
    
    openssl_sign(
        "$base64UrlHeader.$base64UrlPayload",
        $signature,
        $private_key,
        "sha256WithRSAEncryption"
    );
    
    openssl_free_key($private_key);
    
    $base64UrlSignature = zd_base64UrlEncode($signature);
    $jwt = "$base64UrlHeader.$base64UrlPayload.$base64UrlSignature";