352 lines
13 KiB
PHP
352 lines
13 KiB
PHP
<?php
|
|
|
|
namespace Aiko;
|
|
|
|
use Aiko\Log;
|
|
use Firebase\JWT\JWT;
|
|
|
|
class Token
|
|
{
|
|
|
|
public function get_token($area = 'default')
|
|
{
|
|
$token = hash('sha512', mt_rand(0, mt_getrandmax()) . microtime(true));
|
|
$_SESSION['token'] = $token;
|
|
|
|
return $token;
|
|
}
|
|
public function check_token($token, $area = 'default')
|
|
{
|
|
// var_dump($_SESSION);
|
|
$sessiontoken = $this->get_token_from_session('token');
|
|
// var_dump($sessiontoken);
|
|
// exit();
|
|
|
|
|
|
$valid = strlen($sessiontoken) == 128 && strlen($token) == 128 && $sessiontoken == $token;
|
|
|
|
$this->get_token($area); // refresh token
|
|
|
|
return $valid;
|
|
}
|
|
public function get_token_from_url()
|
|
{
|
|
$token = isset($_GET['token']) ? $_GET['token'] : '';
|
|
|
|
return $token;
|
|
}
|
|
|
|
public function get_token_from_session($key)
|
|
{
|
|
$token = isset($_SESSION[$key]) ? $_SESSION[$key] : '';
|
|
|
|
return $token;
|
|
}
|
|
public function getTokenAuthUser()
|
|
{
|
|
$token = hash('sha512', mt_rand(0, mt_getrandmax()) . microtime(true));
|
|
$_SESSION['tokenAuth'] = $token;
|
|
|
|
return $token;
|
|
}
|
|
public function check_tokenAuthUser($token)
|
|
{
|
|
$sessiontoken = $this->get_token_from_session('tokenAuth');
|
|
$valid = strlen($sessiontoken) == 128 && strlen($token) == 128 && $sessiontoken == $token;
|
|
if ($valid) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public function set_cookie()
|
|
{
|
|
$result = password_hash('4pl1k4s1D1sd1K', PASSWORD_DEFAULT, array('cost' => 10));
|
|
// $res = setcookie('XSRF-TOKEN', $result, time() + 86400, $_SERVER['REQUEST_URI'],'',false,false);
|
|
|
|
$res = setcookie('XSRF-TOKEN', $result, time() + 86400, '/');
|
|
if ($res) {
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
public function cek_cookie($clientCookie)
|
|
{
|
|
$result = false;
|
|
if (isset($_COOKIE['XSRF-TOKEN'])) {
|
|
$serverCookie = $_COOKIE['XSRF-TOKEN'];
|
|
$result = $this->cek_hash($clientCookie, $serverCookie);
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
private function cek_hash($clientCookie, $serverCookie)
|
|
{
|
|
if ($clientCookie == $serverCookie) {
|
|
return $this->set_cookie();
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static function wrapToken($jwt, $chipper)
|
|
{
|
|
try {
|
|
if (strlen($chipper) <> 6) {
|
|
throw new \ErrorException('chipper failed');
|
|
}
|
|
$headerPreffix = (int) substr($chipper, 0, 1);
|
|
$headerSuffix = (int) substr($chipper, 1, 1);
|
|
$payloadPreffix = (int) substr($chipper, 2, 1);
|
|
$payloadSuffix = (int) substr($chipper, 3, 1);
|
|
$signPreffix = (int) substr($chipper, 4, 1);
|
|
$signSuffix = (int) substr($chipper, 5, 1);
|
|
|
|
$jwtPart = explode('.', $jwt);
|
|
|
|
$newJwt = self::randomChars($headerPreffix) . $jwtPart[0] . self::randomChars($headerSuffix);
|
|
|
|
$newJwt .= '.' . self::randomChars($payloadPreffix) . $jwtPart[1] . self::randomChars($payloadSuffix);
|
|
|
|
$newJwt .= '.' . self::randomChars($signPreffix) . $jwtPart[2] . self::randomChars($signSuffix);
|
|
|
|
return $newJwt;
|
|
} catch (\Exception $e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static function unWrapToken($jwt, $chipper)
|
|
{
|
|
try {
|
|
if (strlen($chipper) <> 6) {
|
|
throw new \ErrorException('chipper failed');
|
|
}
|
|
|
|
$headerPreffix = (int) substr($chipper, 0, 1);
|
|
$headerSuffix = (int) substr($chipper, 1, 1);
|
|
$payloadPreffix = (int) substr($chipper, 2, 1);
|
|
$payloadSuffix = (int) substr($chipper, 3, 1);
|
|
$signPreffix = (int) substr($chipper, 4, 1);
|
|
$signSuffix = (int) substr($chipper, 5, 1);
|
|
|
|
$jwtPart = explode('.', $jwt);
|
|
|
|
|
|
$newString = self::removePreSuf($jwtPart[0], $headerPreffix, $headerSuffix);
|
|
if ($newString == false) {
|
|
throw new \ErrorException('failed clean wrapper header');
|
|
}
|
|
$header = $newString;
|
|
|
|
$newString = self::removePreSuf($jwtPart[1], $payloadPreffix, $payloadSuffix);
|
|
if ($newString == false) {
|
|
throw new \ErrorException('failed clean wrapper payload');
|
|
}
|
|
$payload = $newString;
|
|
|
|
$newString = self::removePreSuf($jwtPart[2], $signPreffix, $signSuffix);
|
|
if ($newString == false) {
|
|
throw new \ErrorException('failed clean wrapper sign');
|
|
}
|
|
$sign = $newString;
|
|
|
|
return $header . '.' . $payload . '.' . $sign;
|
|
} catch (\ErrorException $e) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
private static function removePreSuf($string, $preffix, $suffix)
|
|
{
|
|
$jum = strlen(trim($string));
|
|
$totWrapper = ($preffix + $suffix);
|
|
$tot = $totWrapper + 10; // set minimum text
|
|
if ($jum > $tot) {
|
|
$total = $jum - $totWrapper;
|
|
$newString = substr($string, $preffix, $total);
|
|
return $newString;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
private static function randomChars($numChars)
|
|
{
|
|
$str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuzwxyz';
|
|
return substr(str_shuffle($str), 0, $numChars);
|
|
}
|
|
|
|
public static function encodeJWT($serverName, $dataUser, $chipper = '000000')
|
|
{
|
|
|
|
try {
|
|
|
|
$log = new Log('1');
|
|
// $publicKey = file_get_contents('/Users/suhendra/mykey/suhendra_rsa.pub');
|
|
|
|
$privateKey = file_get_contents(__SITE_PATH . '/mykey/hcportalprivate.pem');
|
|
|
|
// $privateKey = openssl_get_privatekey('file:///Users/suhendra/mykey/suhendra_rsa','suh3ndr4');
|
|
// var_dump($privateKey);
|
|
|
|
//$tokenId = base64_encode(\mcrypt_create_iv(32));
|
|
$tokenId = base64_encode(\openssl_random_pseudo_bytes(64));
|
|
// $random = mt_rand(0, 999999);
|
|
// $random_string = sha1($random);
|
|
//$tokenId = base64_encode(date('Y-m-d H:i:s'));
|
|
$issuedAt = time();
|
|
$notBefore = time();
|
|
$expire = $notBefore + __EXPIREDJWT; // Adding 10 menit
|
|
$expireReused = $notBefore + __LIFETIMEJWT; // Adding 2hari
|
|
|
|
/*
|
|
* Create the token as an array
|
|
*/
|
|
$data = [
|
|
'iat' => $issuedAt, // Issued at: time when the token was generated
|
|
'jti' => $tokenId, // Json Token Id: an unique identifier for the token / A unique string, could be used to validate a token, but goes against not having a centralized issuer authority.
|
|
'iss' => $serverName, // A string containing the name or identifier of the issuer application. Can be a domain name and can be used to discard tokens from other applications.
|
|
'nbf' => $notBefore, // Timestamp of when the token should start being considered valid. Should be equal to or greater than iat. In this case, the token will begin to be valid 10 seconds
|
|
'exp' => $expire, // Timestamp of when the token should cease to be valid. Should be greater than iat and nbf. In this case, the token will expire 60 seconds after being issued.
|
|
'data' => $dataUser,
|
|
];
|
|
|
|
$jwt = JWT::encode(
|
|
$data, //Data to be encoded in the JWT
|
|
$privateKey, // The signing key
|
|
'RS256' // Algorithm used to sign the token, see https://tools.ietf.org/html/draft-ietf-jose-json-web-algorithms-40#section-3
|
|
);
|
|
|
|
// var_dump($jwt);
|
|
|
|
$newJwt = self::wrapToken($jwt, $chipper);
|
|
// var_dump($newJwt);
|
|
|
|
if ($newJwt == false) {
|
|
throw new \ErrorException('Failed wrap Token');
|
|
}
|
|
|
|
$dataUser['expired'] = $expire;
|
|
$dataHeader = array(
|
|
'jwt' => $newJwt,
|
|
'tokenID' => $tokenId,
|
|
'appID' => $serverName,
|
|
'data' => $dataUser,
|
|
'expired' => $expireReused
|
|
);
|
|
|
|
return $dataHeader;
|
|
} catch (\ErrorException $e) {
|
|
$log->error('encode token token/decodeJWT' . $e->getMessage());
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static function decodeJWT($jwt, $chipper = '000000')
|
|
{
|
|
try {
|
|
$log = new Log('1');
|
|
|
|
$publicKey = file_get_contents(__SITE_PATH . '/mykey/hcportalpublic.pem');
|
|
|
|
$newJwt = self::unWrapToken($jwt, $chipper);
|
|
|
|
$token = JWT::decode($newJwt, $publicKey, array('RS256'));
|
|
|
|
return $token;
|
|
} catch (\DomainException $e) {
|
|
$log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt);
|
|
return false;
|
|
} catch (\InvalidArgumentException $e) {
|
|
$log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt);
|
|
return false;
|
|
} catch (\UnexpectedValueException $e) {
|
|
$log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt);
|
|
return false;
|
|
} catch (\DateTime $e) {
|
|
$log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt);
|
|
return false;
|
|
} catch (\SignatureInvalidException $e) {
|
|
$log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt);
|
|
return false;
|
|
} catch (\BeforeValidException $e) {
|
|
$log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt);
|
|
return false;
|
|
} catch (\Firebase\JWT\ExpiredException $e) {
|
|
$log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt);
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public static function decodeJWTNew($jwt, $chipper = '000000')
|
|
{
|
|
try {
|
|
$log = new Log('1');
|
|
|
|
$publicKey = file_get_contents(__SITE_PATH . '/mykey/hcportalpublic.pem');
|
|
|
|
$newJwt = self::unWrapToken($jwt, $chipper);
|
|
|
|
$token = JWT::decode($newJwt, $publicKey, array('RS256'));
|
|
return $token;
|
|
} catch (\DomainException $e) {
|
|
$log->error('decode token token/decodeJWT 2 ' . $e->getMessage() . 'JWT |' . $jwt);
|
|
return 2;
|
|
} catch (\InvalidArgumentException $e) {
|
|
$log->error('decode token token/decodeJWT 3' . $e->getMessage() . 'JWT |' . $jwt);
|
|
return 3;
|
|
} catch (\UnexpectedValueException $e) {
|
|
$log->error('decode token token/decodeJWT 4' . $e->getMessage() . 'JWT |' . $jwt);
|
|
if ($e->getMessage() == 'Expired token') {
|
|
return 8;
|
|
}
|
|
return 4;
|
|
} catch (\DateTime $e) {
|
|
$log->error('decode token token/decodeJWT 5' . $e->getMessage() . 'JWT |' . $jwt);
|
|
return 5;
|
|
} catch (\SignatureInvalidException $e) {
|
|
$log->error('decode token token/decodeJWT 6' . $e->getMessage() . 'JWT |' . $jwt);
|
|
return 6;
|
|
} catch (\BeforeValidException $e) {
|
|
$log->error('decode token token/decodeJWT 7' . $e->getMessage() . 'JWT |' . $jwt);
|
|
return 7;
|
|
} catch (\Firebase\JWT\ExpiredException $e) {
|
|
$log->error('decode token token/decodeJWT 8' . $e->getMessage() . 'JWT |' . $jwt);
|
|
return 8;
|
|
}
|
|
}
|
|
|
|
public static function decodePlainJWT($jwt, $key = null)
|
|
{
|
|
try {
|
|
$log = new Log('1');
|
|
|
|
$token = JWT::decode($jwt, $key, array('HS256'));
|
|
|
|
return $token;
|
|
} catch (\DomainException $e) {
|
|
$log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt);
|
|
return false;
|
|
} catch (\InvalidArgumentException $e) {
|
|
$log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt);
|
|
return false;
|
|
} catch (\UnexpectedValueException $e) {
|
|
$log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt);
|
|
return false;
|
|
} catch (\Firebase\JWT\SignatureInvalidException $e) {
|
|
$log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt);
|
|
return false;
|
|
} catch (\Firebase\JWT\BeforeValidException $e) {
|
|
$log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt);
|
|
return false;
|
|
} catch (\Firebase\JWT\ExpiredException $e) {
|
|
$log->error('decode token token/decodeJWT' . $e->getMessage() . 'JWT |' . $jwt);
|
|
return false;
|
|
}
|
|
}
|
|
}
|