Last active
February 10, 2023 22:20
-
-
Save FabianPastor/2f33e8512ae2e28975fc5f08e2b30e35 to your computer and use it in GitHub Desktop.
Just a small Telegram Auth Data validator class for PHP.
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 | |
// GET checkdata.php?auth_data={{string_auth_data}} | |
// POST checkdata.php -> DATA auth_data={{string_auth_data}} | |
// auth_data has to be the same string received by the javascript client. | |
require_once "TelegramWebValidator.php"; | |
$data = $_GET["auth_data"] ?? $_POST["auth_data"] ?? null; | |
define('BOT_TOKEN', 'XXXXXXXX:XXXXXXXXXXXXXXXXXXXXXXXX'); // place bot token of your bot here | |
$telegramValidator = new SFPL\Telegram\WebValidator(BOT_TOKEN); | |
$returnValue = new \stdClass; | |
$returnValue->ok = false; | |
try { | |
if (empty($data)) { | |
throw new \Exception("Auth Data not found."); | |
} | |
$returnValue->data = $telegramValidator->checkWebappData($data); | |
//OR for login auth data | |
// $returnValue->data = $telegramValidator->checkLoginAuthData($data); | |
$returnValue->ok = true; | |
} catch (\Throwable $e) { | |
$returnValue->errorType = get_class($e); | |
$returnValue->error = $e->getCode(); | |
$returnValue->description = $e->getMessage(); | |
} | |
// header("Access-Control-Allow-Methods: GET"); | |
// header("Access-Control-Allow-Origin: *"); | |
header('Content-type: application/javascript;charset=utf-8'); | |
echo json_encode($returnValue); |
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 | |
// TelegramWebValidator.php | |
namespace SFPL\Telegram; | |
class WebDataException extends \Exception{}; | |
class WebValidator | |
{ | |
private string $bottoken; | |
private int $time_to_expire = 86400; | |
public function __construct(string $bottoken, int $time_to_expire = null) | |
{ | |
$this->bottoken = $bottoken; | |
if (!empty($time_to_expire)) { | |
$this->time_to_expire = $time_to_expire; | |
} | |
} | |
public function checkLoginAuthData(string $data): array | |
{ | |
return $this->checkData($data, $this->secretKeyLogin()); | |
} | |
public function checkWebappData(string $data): array | |
{ | |
return $this->checkData($data, $this->secretKeyWebapp()); | |
} | |
public function generateLoginAuthDataHash(array $data): string | |
{ | |
return $this->generateHash($data, $this->secretKeyLogin()); | |
} | |
public function generateWebAppDataHash(array $data): string | |
{ | |
return $this->generateHash($data, $this->secretKeyWebapp()); | |
} | |
public function generateHash(array $data, $secret_key){ | |
$data_check_string = $this->dataSorting($data); | |
return hash_hmac('sha256', $data_check_string, $secret_key); | |
} | |
private function checkData(string $data, $secret_key): array | |
{ | |
parse_str($data, $auth_data); | |
if (!isset($auth_data["hash"])) { | |
throw new WebDataException('Data hash not defined', 1); | |
} | |
if ($secret_key === false) { | |
throw new WebDataException('Invalid Secret key', 2); | |
} | |
$hash = $this->generateHash($auth_data, $secret_key); | |
if (!$this->validHashes($hash, $auth_data["hash"])) { | |
throw new WebDataException('Received data is not valid', 3); | |
} | |
if (!$this->validAuthDate($auth_data['auth_date'])) { | |
throw new WebDataException('Data is outdated', 4); | |
} | |
return $auth_data; | |
} | |
public function dataSorting(array $data): string | |
{ | |
unset($data['hash']); | |
$data_check_arr = []; | |
foreach ($data as $key => $value) { | |
$data_check_arr[] = $key . '=' . $value; | |
} | |
sort($data_check_arr); | |
$data_check_string = implode("\n", $data_check_arr); | |
return $data_check_string; | |
} | |
private function secretKeyLogin() | |
{ | |
return hash('sha256', $this->bottoken, true); | |
} | |
private function secretKeyWebapp() | |
{ | |
return hash_hmac('sha256', $this->bottoken, "WebAppData", true); | |
} | |
public function validHashes($computed_hash, $provided_hash): bool | |
{ | |
return (strcmp($computed_hash, $provided_hash) === 0); | |
} | |
public function validAuthDate($date): bool | |
{ | |
return ((time() - $date) <= $this->time_to_expire); | |
} | |
public function sendMethod($object) | |
{ | |
$response = json_decode(file_get_contents("https://api.telegram.org/bot{$this->bottoken}/", false, stream_context_create([ | |
"http" => [ | |
'method' => 'POST', | |
'header' => [ | |
'Content-type: application/json', | |
], | |
'content' => json_encode($object), | |
"ignore_errors" => true, | |
] | |
]))); | |
$response->query = $object; | |
return $response; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment