php-jwt

Simple and Secure JWT Signer/Verifier

Introduction

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

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.

Why?

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.

How?

Requirements

On modern PHP versions only paragonie/constant_time_encoding is a dependency, on older versions some polyfills are used. See composer.json.

Use

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.tuxed.net/fkooman/php-jwt"
    },
    ...
],
 
"require": {
    "fkooman/jwt": "^1",
    ...
},

You can also download the signed source code archive here.

Keys

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!

RS256 (RSA)

Use the openssl command line to generate they public and private key:

$ openssl genrsa --out rsa.key 2048
$ openssl rsa -in rsa.key -pubout -out rsa.pub

The RSA key MUST have at least 2048 bits. 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

HS256 (HMAC)

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);

EdDSA (Ed25519)

<?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.

API

This section describes how to use the various JWT types.

RS256

<?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.

HS256

<?php
 
$h = new \fkooman\Jwt\HS256(
    \fkooman\Jwt\Keys\HS256\SecretKey::fromEncodedString(
        '5SBq2gMQFsy6ToGH0SS8CLFPCGxxFl8uohZUooCq5ps'
    )
);
$jwtStr = $h->encode(['foo' => 'bar']);
var_dump($h->decode($jwtStr));

EdDSA (Ed25519)

<?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.

Example

See the example/ directory for a working example.

Testing

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

$ /path/to/composer install
$ vendor/bin/phpunit

Benchmark

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

$ /path/to/phpbench run