Last active
January 21, 2021 08:45
-
-
Save gaffling/6395c40aa706da3e0a9f63b47d6b7857 to your computer and use it in GitHub Desktop.
[Token Class] Simple PHP JSON Web Token (JWT) #php #class #jwt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/** | |
* JWT (JSON Web Token) Implementation | |
* | |
* Minimum implementation used by Realtime auth, based on this: | |
* | |
* READ https://codeofaninja.com/2018/09/rest-api-authentication-example-php-jwt-tutorial.html | |
* INFO http://self-issued.info/docs/draft-jones-json-web-token-01.html | |
* CODE https://github.com/luciferous/jwt | |
* DOCU https://github.com/zxsleebu/jwt | |
* TEST https://jwt.io/ | |
* | |
* @author Neuman Vong <neuman@twilio.com> | |
* @see CRYPT <http://phpclasses.org/blog/package/11662/post/1-php-encrypt-and-decrypt-sensitive-data.html> | |
*/ | |
class JWT { | |
/** | |
* @param string $token The token | |
* @param string|null $key The secret key | |
* @param bool $crypt Use crypt | |
* @param bool $verify If false the verification processs is skipped | |
* | |
* @return string The data as an array | |
*/ | |
public static function decode($token, $key = null, $crypt = true, $verify = true) /* ENTSCHLÜSSELN */ | |
{ | |
// Also encrypt the data with the same key | |
if ($crypt === true) $token = JWT::decrypt($key, $token); | |
$bad = 0; | |
$token_segments = explode('.', $token); | |
if (count($token_segments) != 3) { | |
$bad = 1; | |
} else { // vanGato | |
list($head_b64, $data_b64, $crypto_b64) = $token_segments; | |
if (null === ($header = JWT::jsonDecode(JWT::urlsafeB64Decode($head_b64)))) { | |
$bad = 1; | |
} | |
if (null === $data = JWT::jsonDecode(JWT::urlsafeB64Decode($data_b64))) { | |
$bad = 1; | |
} | |
$sig = JWT::urlsafeB64Decode($crypto_b64); | |
if ($verify) { | |
if (empty($header->alg)) { | |
$bad = 1; | |
} | |
if ($sig != JWT::sign("$head_b64.$data_b64", $key, $header->alg)) { | |
$bad = 1; | |
} | |
// vanGato - Let the token expire if $verify=true but no "exp" is set | |
if (!isset(json_decode(json_encode($data), true)["exp"])) { | |
$bad = 1; | |
} else if (null !== ($expire = json_decode(json_encode($data), true)["exp"])) { | |
if ($expire < time()){ | |
$bad = 1; | |
} | |
} | |
} | |
} | |
if (!$bad) { | |
return json_decode(json_encode($data), true); | |
} | |
} | |
/** | |
* @param object|array $data The data as an array | |
* @param string $key The secret key | |
* @param bool $crypt Use crypt | |
* @param string $algo The signing algorithm | |
* | |
* @return string The token | |
*/ | |
public static function encode($data, $key, $crypt = true, $algo = 'HS256') /* VERSCHLÜSSELN */ | |
{ | |
$header = array('typ' => 'JWT', 'alg' => $algo); | |
$segments = array(); | |
$segments[] = JWT::urlsafeB64Encode(JWT::jsonEncode($header)); | |
$segments[] = JWT::urlsafeB64Encode(JWT::jsonEncode($data)); | |
$signing_input = implode('.', $segments); | |
$signature = JWT::sign($signing_input, $key, $algo); | |
$segments[] = JWT::urlsafeB64Encode($signature); | |
$return = implode('.', $segments); | |
// Also encrypt the data with the same key | |
if ($crypt === true) $return = JWT::encrypt($key, $return); | |
return $return; | |
} | |
/** | |
* @param string $data The data to sign | |
* @param string $key The secret key | |
* @param string $method The signing algorithm | |
* | |
* @return string An encrypted message | |
*/ | |
public static function sign($data, $key, $method = 'HS256') | |
{ | |
$methods = array( | |
'HS256' => 'sha256', | |
'HS384' => 'sha384', | |
'HS512' => 'sha512', | |
); | |
if (empty($methods[$method])) { | |
// error | |
} | |
if (!empty($methods[$method])) { | |
return hash_hmac($methods[$method], $data, $key, true); // true = return RAW binary | |
} | |
} | |
/** | |
* @param string $input JSON string | |
* | |
* @return object Object representation of JSON string | |
*/ | |
public static function jsonDecode($input) | |
{ | |
$obj = json_decode($input); | |
if (function_exists('json_last_error') && $errno = json_last_error()) { | |
} | |
else if ($obj === null && $input !== 'null') { | |
// error | |
} | |
return $obj; | |
} | |
/** | |
* @param object|array $input A PHP object or array | |
* | |
* @return string JSON representation of the PHP object or array | |
*/ | |
public static function jsonEncode($input) | |
{ | |
$json = json_encode($input); | |
if (function_exists('json_last_error') && $errno = json_last_error()) { | |
JWT::handleJsonError($errno); | |
} | |
else if ($json === 'null' && $input !== null) { | |
// error | |
} | |
return $json; | |
} | |
/** | |
* @param string $input A base64 encoded string | |
* | |
* @return string A decoded string | |
*/ | |
public static function urlsafeB64Decode($input) | |
{ | |
$remainder = strlen($input) % 4; | |
if ($remainder) { | |
$padlen = 4 - $remainder; | |
$input .= str_repeat('=', $padlen); | |
} | |
return base64_decode(strtr($input, '-_', '+/')); | |
} | |
/** | |
* @param string $input Anything really | |
* | |
* @return string The base64 encode of what you passed in | |
*/ | |
public static function urlsafeB64Encode($input) | |
{ | |
return str_replace('=', '', strtr(base64_encode($input), '+/', '-_')); | |
} | |
/** | |
* @param int $err_no An error number from json_last_error() | |
* | |
* @return void | |
*/ | |
private static function handleJsonError($err_no) | |
{ | |
$messages = array( | |
JSON_ERROR_DEPTH => 'Maximum stack depth exceeded', | |
JSON_ERROR_CTRL_CHAR => 'Unexpected control character found', | |
JSON_ERROR_SYNTAX => 'Syntax error, malformed JSON' | |
); | |
// vanGato | |
if (isset($messages[$err_no])) { | |
die($messages[$err_no]); | |
} else { | |
die('Unknown JSON error: ' . $err_no); | |
} | |
} | |
/** | |
* vanGato | |
* @param string $key The secret key | |
* @param string $string_to_encrypt The string data to encrypt | |
* @param string $type The return type base64 or hex (default: base64) | |
* | |
* @return string The encrypted string | |
*/ | |
private static function encrypt($key, $string_to_encrypt, $type='base64') | |
{ | |
$key = md5($key); | |
// mcrypt_encrypt() DEPRECATED as of PHP 7.1.0 and REMOVED as of PHP 7.2.0 | |
$rtn = openssl_encrypt($string_to_encrypt, 'bf-ecb', $key, true); | |
if (strtolower($type)=='base64') { | |
$rtn = base64_encode($rtn); | |
$rtn = rtrim($rtn, '='); | |
} else { | |
$rtn = bin2hex($rtn); | |
} | |
return($rtn); | |
} | |
/** | |
* vanGato | |
* @param string $key The secret key | |
* @param string $string_to_encrypt The string data to decrypt | |
* @param string $type The input type base64 or hex (default: base64) | |
* | |
* @return string The decrypted string | |
*/ | |
private static function decrypt($key, $string_to_decrypt, $type='base64') | |
{ | |
$key = md5($key); | |
if (strtolower($type)=='base64') { | |
$string_to_decrypt = base64_decode($string_to_decrypt); | |
} else { | |
$string_to_decrypt = hex2bin($string_to_decrypt); | |
} | |
// mcrypt_decrypt() DEPRECATED as of PHP 7.1.0 and REMOVED as of PHP 7.2.0 | |
$rtn = openssl_decrypt($string_to_decrypt, 'bf-ecb', $key, true); | |
return($rtn); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
/* -------------------------------------------------------------- */ | |
/* [Token Class] Simple PHP JSON Web Token (JWT) #php #class #jwt */ | |
/* -------------------------------------------------------------- */ | |
error_reporting(E_ALL | E_STRICT); | |
ini_set('display_errors', 1); | |
$root = dirname(__FILE__); | |
require_once $root . '/JWT.php'; | |
unset($root); | |
$prefix = '<hr size="1"><pre><b>'; | |
$suffix = PHP_EOL . PHP_EOL . '</pre>'; | |
$data = array( | |
"exp" => 91608212663, // Expiration date in Unix time format | |
"name" => "John Doe", // Other data | |
); | |
$token = JWT::encode($data, 'my_key'); | |
echo $prefix . 'SET DATA</b><br>'; var_dump($data); echo $suffix; | |
echo $prefix . 'TOKEN</b><br>' . $token . $suffix; | |
echo $prefix . 'GET DATA</b><br>'; var_dump(JWT::decode($token, 'my_key')); echo $suffix; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment