Small JSON Web Signature implementation
remove src/Binary.php
Merge branch 'v2'
add Forgejo CI files



You can also use your local clone with git send-email.

Summary: Small JSON Web Signature implementation

Description: Small and secure JSON Web Signature implementation written in PHP. It only supports RS256 and EdDSA.

License: MIT


This is small JSON Web Token implementation. It only supports signatures with the following signature algorithms:

  • RS256 (RSASSA-PKCS1-v1_5 using SHA-256)
  • EdDSA (Ed25519, RFC 8037)

The RS256 algorithm is used by (almost) every deployment. However, we do not want to restrict ourselves to just that algorithm, and in addition implement EdDSA, which is the most modern, secure and fast algorithm.

The library does NOT support encryption/decryption due to the can of worms that would open.


Quite a number of JWT implementations exist for PHP, varying in quality. However, JWT can be insecure, so it is very important to get things right and as simple as possible from a security perspective. This means implementing the absolute minimum to support JWT, in a secure way. Simplicity and security is more important than fully supporting every nook and cranny of the specification.


  • Only supports RS256 and EdDSA through separate classes, the header is NOT used to determine the algorithm when verifying signatures, actually, the header is only inspected after verifying the signature;
  • All keys are validated before use and wrapped in "Key" objects to make sure they are of the correct format. Helper methods are provided to load / save / generate keys;
  • Does NOT support the crit header key. If a token is presented with the crit header key it will be rejected;
  • Verifies the exp and nbf payload field if present to make sure the token is already and still valid.


  • PHP >= 7.4.0
  • php-openssl (for RS256)
  • php-sodium (for EdDSA)


Currently php-jwt is not hosted on Packagist. It may be added in the future. In your composer.json:

"repositories": [
        "type": "vcs",
        "url": "https://git.sr.ht/~fkooman/php-jwt"

"require": {
    "fkooman/jwt": "v2.x-dev",

You can also download the signed source code archive from the project page under "release notes".


Example scripts are included that allows you to safely generate keys for all algorithms:

$ php examples/generate_key_RS256.php
$ php examples/generate_key_EdDSA.php

The scripts take the --kid parameter to allow you to specify the Key ID, e.g.:

$ php examples/generate_key_EdDSA.php --kid my-key-id
Secret Key: {"kty":"OKP","crv":"Ed25519","x":"C20lkWDOfKIN77f5uRO-maDY-c_3bz8xp5XXyDU4Hsc","d":"3lZpvyzEM7-u1wzet5zwgFgt5-b1DnUaKvI4mtjoP-E","alg":"EdDSA","use":"sig","kid":"my-key-id"}
Public Key: {"kty":"OKP","crv":"Ed25519","x":"C20lkWDOfKIN77f5uRO-maDY-c_3bz8xp5XXyDU4Hsc","alg":"EdDSA","use":"sig","kid":"my-key-id"}

If you omit the --kid parameter a Key ID based on the current date is used.


This section describes how to use the API to generate a new key and to "encode" / "decode" JWTs:


use fkooman\Jwt\EdDSA\SecretKey as EdDSASecretKey;
use fkooman\Jwt\Jwt;
use fkooman\Jwt\RS256\SecretKey as RS256SecretKey;

echo '** EdDSA **' . PHP_EOL;
$secretKey = EdDSASecretKey::generate();
$jwtStr = Jwt::encode($secretKey, ['foo' => 'bar']);
echo 'JWT: ' . $jwtStr . PHP_EOL;
var_dump(Jwt::decode($secretKey->publicKey(), $jwtStr));

echo '** RS256 **' . PHP_EOL;
$secretKey = RS256SecretKey::generate();
$jwtStr = Jwt::encode($secretKey, ['foo' => 'bar']);
echo 'JWT: ' . $jwtStr . PHP_EOL;
var_dump(Jwt::decode($secretKey->publicKey(), $jwtStr));


See the examples/ directory for working examples.


You can run the included test suite after cloning the repository:

$ make test


You can use PHPBench to run some benchmarks comparing the various signature algorithms.

$ make bench