update CHANGES
restore Binary class
major cleanups, drop paragonie/constant_time_encoding dependency
Summary: Small JSON Web Signature implementation
Description: Small and secure JSON Web Signature implementation written in PHP. It only supports HS256, RS256 and EdDSA.
License: MIT
This is small JSON Web Token implementation. It only supports signatures with the following signature algorithms:
HS256
(HMAC
using SHA-256
)RS256
(RSASSA-PKCS1-v1_5
using SHA-256
)EdDSA
(Ed25519
, RFC 8037)The first two seem to be the most widely deployed JWT signature algorithms. The library does NOT support encryption/decryption due to the can of worms that would open. It MAY support encryption/decryption in the future, but not with RSA.
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.
RS256
, HS256
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;crit
header key it will be
rejected;exp
and nbf
payload field if present to make sure the token
is already and still valid.php-hash
(for HS256
)php-openssl
(for RS256
)Installing php-sodium
(PHP >= 7.2) or php-libsodium
packages, (PHP < 7.2)
are highly recommended when using 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": "^1",
...
},
You can also download the signed source code archive from the project page under "release notes".
Below we show how to generate keys for the various JWT algorithms. Do NOT use any other way unless you know what you are doing!
Use the openssl
command line to generate they public and private key:
$ openssl genrsa --out rsa.key 3072
$ openssl rsa -in rsa.key -pubout -out rsa.pub
The RSA key MUST have
at least 2048 bits. It is
highly recommended to use at least 3072 when you plan to use the same key for
the next couple of years. The above command will generate a private key in
rsa.key
and the public key in rsa.pub
. Those files can be used with the
PublicKey
and PrivateKey
key wrapping classes.
To inspect a public key:
$ openssl rsa -pubin -in rsa.pub -noout -text
As this is a HMAC, there is only one key both for signing and verifying the JWT.
<?php
// generating and saving a key
$secretKey = \fkooman\Jwt\Keys\HS256\SecretKey::generate();
$encodedString = $secretKey->encode();
// loading a key
$secretKey = \fkooman\Jwt\Keys\HS256\SecretKey::fromEncodedString($encodedString);
<?php
// generating and saving a key
$secretKey = \fkooman\Jwt\Keys\EdDSA\SecretKey::generate();
$encodedString = $secretKey->encode();
// loading a key
$secretKey = \fkooman\Jwt\Keys\EdDSA\SecretKey::fromEncodedString($encodedString);
The public key can be obtained from the secret key by calling the
getPublicKey
method on the SecretKey
object.
This section describes how to use the various JWT types.
<?php
$r = new \fkooman\Jwt\RS256(
\fkooman\Jwt\Keys\RS256\PublicKey::load('rsa.pub'),
\fkooman\Jwt\Keys\RS256\PrivateKey::load('rsa.key')
);
$jwtStr = $r->encode(['foo' => 'bar']);
var_dump($r->decode($jwtStr));
The PrivateKey
parameter is optional. Do not specify it if you only want to
verify JWTs. Of course, you need to specify it when you want to sign JWTs.
<?php
$h = new \fkooman\Jwt\HS256(
\fkooman\Jwt\Keys\HS256\SecretKey::fromEncodedString(
'5SBq2gMQFsy6ToGH0SS8CLFPCGxxFl8uohZUooCq5ps'
)
);
$jwtStr = $h->encode(['foo' => 'bar']);
var_dump($h->decode($jwtStr));
<?php
$secretKey = \fkooman\Jwt\Keys\EdDSA\SecretKey::fromEncodedString(
'yvo12M7L4puipaUwuuDz_1SMDLz7VPcgcny-OkOHnIEamcDtjH31m6Xlw6a9Ib5dp5A-vHMdzIhUQxUMreqxPg'
);
$publicKey = $secretKey->getPublicKey();
$r = new \fkooman\Jwt\EdDSA(
$publicKey,
$secretKey
);
$jwtStr = $r->encode(['foo' => 'bar']);
var_dump($r->decode($jwtStr));
The SecretKey
parameter is optional. Do not specify it if you only want to
verify JWTs. Of course, you need to specify it when you want to sign a JWT.
See the example/
directory for a working example.
You can run the included test suite after cloning the repository:
$ /path/to/composer install
$ vendor/bin/phpunit
You can use PHPBench to run some benchmarks comparing the various signature algorithms.
$ /path/to/phpbench run