zenstruck/jwt
, (*1)
Provides a lightweight implementation of the JWS (JSON Web Signature)
specification. This library is a fork of namshi/jose., (*2)
Requirements
-
PHP 5.4.8+ (tested on 5.4, 5.5, 5.6, 7 and HHVM)
-
(Optional) OpenSSL extension (when using RSA/ECDSA signers)
-
(Optional) symfony/polyfill-php56 library (when HMAC signers
in PHP versions less than 5.6)
Installation
composer require zenstruck/jwt
When using an HMAC signer in PHP versions less than 5.6, (*3)
composer require symfony/polyfill-php56
Basic Usage
-
Create, encode and send a token to the user:, (*4)
use Zenstruck\JWT\Token;
use Zenstruck\JWT\Signer\HMAC\HS256;
// create the token
$token = new Token([
'username' => 'kevin', // custom claim
'iss' => 'zenstruck', // set issuer
'exp' => time() + 86400, // set expiry claim to 1 day from now
]);
// can access claims
$token->get('username'); // kevin
$token->get('non-existant'); // null
// sign the token
$token->sign(new HS256(), 'my secret key');
$encodedTokenForUser = (string) $token;
// ...pass to user
-
Fetch encoded token from user, decode, verify, validate and access custom claims, (*5)
use Zenstruck\JWT\Token;
use Zenstruck\JWT\Signer\HMAC\HS256;
use Zenstuck\JWT\Validator\ExpiresAtValidator;
use Zenstuck\JWT\Validator\IssuerValidator;
use Zenstruck\JWT\Exception\MalformedToken;
use Zenstruck\JWT\Exception\UnverifiedToken;
use Zenstruck\JWT\Exception\Validation\ExpiredToken;
use Zenstruck\JWT\Exception\ValidationFailed;
$encodedTokenFromUser = // ...fetched from user
try {
$decodedToken = Token::fromString($encodedTokenFromUser);
} catch (MalformedToken $e) {
// token is not correctly formed
}
// at this point $decodedToken is a JWT but is not yet verified or validated
try {
$decodedToken->verify(new HS256(), 'my secret key');
} catch (UnverifiedToken $e) {
// token could not be verified
}
try {
$decodedToken->validate(new ExpiresAtValidator());
$decodedToken->validate(new IssuerValidator('zenstruck'));
} catch (ExpiredToken $e) {
// the token has expired
} catch (ValidationFailed $e) {
// token is invalid - in this case, the issuer does not match
}
// can access claims
$token->get('username'); // kevin
$token->get('non-existant'); // null
Token Builder
use Zenstruck\JWT\TokenBuilder;
$token = (new TokenBuilder())
->issuer('kevin')
->subject('zenstruck\jwt')
->audience('php community')
->expiresAt(new \DateTime('+1 day'))
->notBefore(new \DateTime('+1 hour'))
->issuedAt() // can pass \DateTime object - uses current time by default
->id('foo')
->set('foo', 'bar') // set custom claims
->create(); // instance of Zenstruck\JWT\Token
Signers
HMAC
These signers require an identical key string to be used for signing and validating., (*6)
Algorithm |
Signer Class |
HS256 |
Zenstruck\JWT\Signer\HMAC\HS256 |
HS384 |
Zenstruck\JWT\Signer\HMAC\HS384 |
HS512 |
Zenstruck\JWT\Signer\HMAC\HS512 |
Usage
$token = // ... instance of Zenstruck\JWT\Token
$signer = // an instance of one of the classes in the table above
$token->sign($signer, 'my secret key');
$token->verify($signer, 'my secret key'); // verified
$token->verify($signer, 'invalid secret key'); // unverified - exception thrown
RSA/ECDSA (OpenSSL)
These signers require a private key for signing and a public key for verifying., (*7)
-
PrivateKey: a
string
(key contents or filename), resource
or instance of
Zenstruck\JWT\Signer\OpenSSL\PrivateKey
-
PublicKey: a
string
(key contents or filename), resource
or instance of
Zenstruck\JWT\Signer\OpenSSL\PublicKey
-
Keychain: instance of
Zenstruck\JWT\Signer\OpenSSL\Keychain
contains both a public and private key.
Can be passed as the key to both Signer::sign()
and Signer::verify()
.
Algorithm |
Signer Class |
RS256 |
Zenstruck\JWT\Signer\OpenSSL\RSA\RS256 |
RS384 |
Zenstruck\JWT\Signer\OpenSSL\RSA\RS384 |
RS512 |
Zenstruck\JWT\Signer\OpenSSL\RSA\RS512 |
ES256 |
Zenstruck\JWT\Signer\OpenSSL\ECDSA\ES256 |
ES384 |
Zenstruck\JWT\Signer\OpenSSL\ECDSA\ES384 |
ES512 |
Zenstruck\JWT\Signer\OpenSSL\ECDSA\ES512 |
Usage
$token = // ... instance of Zenstruck\JWT\Token
$signer = // an instance of one of the classes in the table above
$privateKey = // can be string, resource, filename, instance of Zenstruck\JWT\Signer\OpenSSL\PrivateKey, instance of Zenstruck\JWT\Signer\OpenSSL\Keychain
$publicKey = // can be string, resource, filename, instance of Zenstruck\JWT\Signer\OpenSSL\PublicKey, instance of Zenstruck\JWT\Signer\OpenSSL\Keychain
$token->sign($signer, $privateKey);
$token->verify($signer, $publicKey); // verified
$token->verify($signer, '/path/to/unmatched/public/key'); // unverified - exception thrown
Keychain
A keychain contains both a public and private key. When passed a keychain as the key, the signer uses
the proper key for the operation., (*8)
use Zenstruck\JWT\Signer\OpenSSL\Keychain;
$token = // ... instance of Zenstruck\JWT\Token
$signer = // an instance of one of the classes in the table above
$privateKey = // can be string, resource, filename, instance of Zenstruck\JWT\Signer\OpenSSL\PrivateKey
$publicKey = // can be string, resource, filename, instance of Zenstruck\JWT\Signer\OpenSSL\PublicKey
$keychain = new Keychain($publicKey, $privateKey, 'my passphrase');
$token->sign($signer, $keychain);
$token->verify($signer, $keychain); // verified
Validation
Validator |
Description |
Zenstruck\JWT\Validator\IssuerValidator |
Ensures iss claim exists and matches expected value |
Zenstruck\JWT\Validator\SubjectValidator |
Ensures sub claim exists and matches expected value |
Zenstruck\JWT\Validator\AudienceValidator |
Ensures aud claim exists and matches expected value |
Zenstruck\JWT\Validator\ExpiresAtValidator |
Ensures exp claim exists is not greater than expected time |
Zenstruck\JWT\Validator\NotBeforeValidator |
Ensures nbf claim exists is not less than expected time |
Zenstruck\JWT\Validator\IssuedAtValidator |
Ensures iat claim exists and matches expected value |
Zenstruck\JWT\Validator\IdAtValidator |
Ensures jti claim exists and matches expected value |
Zenstruck\JWT\Validator\ChainValidator |
Combines any of the above validators together |
Usage
use Zenstruck\JWT\Validator\IssuerValidator;
use Zenstruck\JWT\Validator\AudienceValidator;
use Zenstruck\JWT\Validator\ChainValidator;
$token = // ... instance of Zenstruck\JWT\Token
$validator = new ChainValidator([new IssuerValidator(), new AudienceValidator()]);
try {
$token->validate($validator);
} catch (ValidationFailed $e) {
$reason = $e->getMessage();
}
ValidatorBuilder
$validator = (new ValidatorBuilder())
->issuer('kevin')
->subject('zenstruck\jwt')
->audience('php community')
->expiresAt()
->notBefore()
->issuedAt(time())
->id('foo')
->create(); // instance of Zenstruck\JWT\Validator\ChainValidator