FastSitePHP\Security\Crypto\JWT

JSON Web Tokens (JWT)

Source Code

GitHub

Example Code

Security - Encode and Decode a JSON Web Token (JWT)

// The JWT Payload can be either an Object or an Array (Dictionary).
$payload = [
    'User' => 'John Doe',
    'Roles' => ['Admin', 'SQL Editor']
];

// Generate a Key for Encoding (Signing).
// The key is a long hex string of secure random bytes.
// The key would typically be saved with your app or in config.
$jwt = new \FastSitePHP\Security\Crypto\JWT();
$key = $jwt->generateKey();

// Encode and Decode JWT with the Crypto Helper Class with Config Settings.
// When using the default parameters with the helper class the data has a
// 1-hour timeout.
$app->config['JWT_KEY'] = $key;
$token = \FastSitePHP\Security\Crypto::encodeJWT($payload);
$data  = \FastSitePHP\Security\Crypto::decodeJWT($token);

// Encode (Sign) and Decode (Verify) using the JWT Class. When using
// default settings with the JWT Class, no timeout is specified, all
// claims are validated, and a secure key is required.
$token = $jwt->encode($payload, $key);
$data  = $jwt->decode($token, $key);

// Add Claims to the Payload and use an Insecure Key for Compatibility
// with other sites (Often online demos of JWT are shown using simple
// passwords for the key). By default keys are required to be secure
// with proper length and in either Base64 or Hex format.

$payload = $jwt->addClaim($payload, 'exp', '+10 minutes');
$payload = $jwt->addClaim($payload, 'iss', 'example.com');

$jwt
    ->useInsecureKey(true)
    ->allowedIssuers(['example.com']);

$insecure_key = 'password123';
$token = $jwt->encode($payload, $insecure_key);
$data  = $jwt->decode($token, $insecure_key);

Security - Encode and Decode JWT using RSA

// The JWT Payload can be either an Object or an Array (Dictionary).
$payload = new \stdClass;
$payload->User = 'John Doe';
$payload->Roles = ['Admin', 'SQL Editor'];

// Create JWT Class, specify 'RS256' Algoritm, and generate Key Pair
$jwt = new \FastSitePHP\Security\Crypto\JWT();
$jwt
    ->algo('RS256')
    ->allowedAlgos(['RS256']);

list($private_key, $public_key) = $jwt->generateKey();

// Encode (Sign) and Decode (Verify)
$token = $jwt->encode($payload, $private_key);
$data  = $jwt->decode($token, $public_key);

Methods

__construct()

Class Constructor

If using PHP 5.5 or below then [hash_equals()] is polyfilled, and [bin2hex()] and [hex2bin()] are polyfilled for PHP 5.3.

generateKey($key_type = 'base64')

Generate a secure key based on the algorithm specified from the function [algo()]. When using HMAC the key is returned in either Base64 of Hex format depending on the $type parameter (defaults to Base64); and when using RSA an array is returned in the format of [private_key, public_key].

Returns: string | array

encode($payload, $key)

Encode and Create a JWT. The algorithm to use can be specified from the function [algo()]. By default a secure key is required and one can be generated from the function [generateKey()]. If a weak key is required for compatibility with other code see the function [useInsecureKey()].

Returns: string - JSON Web Token (JWT)

decode($token, $key)

Decode and Verify a JWT. If the token is not valid null will be returned unless [exceptionOnError(true)] is set and then an exception will be thrown.

Unless settings are changed from [allowedAlgos()] only the default algorithm 'HS256' is accepted for decoding.

If the payload has a claim defined then it will be validated by default. This can be turned off by calling [validateDefinedClaims(false)].

To require and validate specific claims use the [require*()/allowed*()] getter/setter functions of this class.

Returns: array | null - The payload that was originally encoded.

addClaim($payload, $claim, $value)

Helper function to add a JWT field value to either an array or object. Use this prior to calling [encode()]. Time fields ['exp', 'nbf', 'iat'] must be either an integer representing a Unix Timestamp or a string that is valid for the PHP function [strtotime()].

Example to expire a Token after 10 minutes:
    $payload = $jwt->addClaim($payload, 'exp', '+10 minutes');

Returns: array | object - The modified payload

exceptionOnError($value = null)

Getter / Setter Property

By default [decode()] returns null when a JWT cannot be validated or invalid settings are used. When the value of this function is set to [true] then an exception will be thrown instead.

Returns: bool | $this

algo($new_value = null)

Getter / Setter Property

Get or set the default JWT Algorithm to use, for supported algorithms see comments in [allowedAlgos()]. Defaults to 'HMAC' with 'SHA256'.

Returns: string | $this

allowedAlgos(array $new_value = null)

Getter / Setter Property

Get or set an array of allowed JWT Algorithms to accept when decoding.

HMAC [HS256, HS384, HS512] and RSA [RS256, RS384, RS512] are supported. Elliptic Curve Digital Signature Algorithms (ECDSA) [ES256, ES384, ES512] are not supported by this class because PHP's OpenSSL implementation does not provide built-in support.

If need to use (ECDSA) with PHP there are several options:
  Encode/Decode Fast (PHP C Extension):
    https://github.com/cdoco/php-jwt
  Encode/Decode Slower (Using PHP Code):
    https://github.com/lcobucci/jwt
    https://github.com/web-token/jwt-framework

Returns: array | $this

useInsecureKey($new_value = null)

Getter / Setter Property

Get or set Key Requirement when using and HMAC JWT [HS256, HS384, HS512]. Defaults to [false] and with default settings a strong key size must be used.

This should only be set to [true] if compatibility with other code is needed. Often online samples use common passwords such as 'secret' when signing JWT's which is why this setting was created.

Returns: bool | $this

validateDefinedClaims($new_value = null)

Getter / Setter Property

Get or set whether defined claims must be validated when [decode()] is called. Defaults to true.

Example if the payload has a value for [exp] then by default the JWT Expiration Time is checked otherwise [requireExpireTime()] would have to be set.

Returns: bool | $this

allowedIssuers(array $new_value = null)

Getter / Setter Property

Get or set an allowed list of values for "iss" (Issuer) Claim

Returns: array | null | $this

requireSubject($new_value = null)

Getter / Setter Property

Get or set validation for the "sub" (Subject) Claim

Returns: string | null | $this

allowedAudiences(array $new_value = null)

Getter / Setter Property

Get or set an allowed list of audience values for the "aud" (Audience) Claim

Returns: array | null | $this

requireExpireTime($new_expiration_time = null, $leeway = null)

Getter / Setter Property

Get or set validation for the "exp" (Expiration Time) Claim

Returns: array | $this

requireNotBefore($new_not_before_time = null, $leeway = null)

Getter / Setter Property

Get or set validation for the "nbf" (Not Before) Claim

Returns: array | $this

requireIssuedAt($new_value = null)

Getter / Setter Property

Get or set validation for the "iat" (Issued At) Claim

Returns: bool | $this

requireJwtId($new_value = null)

Getter / Setter Property

Get or set validation for the "jti" (JWT ID) Claim

Returns: bool | $this