JWT introduce other algorithms
This commit is contained in:
parent
7a4222ac39
commit
c277aababc
@ -72,7 +72,7 @@ namespace Api\Mail {
|
|||||||
"subject" => "Test E-Mail",
|
"subject" => "Test E-Mail",
|
||||||
"body" => "Hey! If you receive this e-mail, your mail configuration seems to be working.",
|
"body" => "Hey! If you receive this e-mail, your mail configuration seems to be working.",
|
||||||
"gpgFingerprint" => $this->getParam("gpgFingerprint"),
|
"gpgFingerprint" => $this->getParam("gpgFingerprint"),
|
||||||
"asnyc" => false
|
"async" => false
|
||||||
));
|
));
|
||||||
|
|
||||||
$this->lastError = $req->getLastError();
|
$this->lastError = $req->getLastError();
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
|
|
||||||
namespace Configuration;
|
namespace Configuration;
|
||||||
|
|
||||||
|
use Driver\Logger\Logger;
|
||||||
use Driver\SQL\Query\Insert;
|
use Driver\SQL\Query\Insert;
|
||||||
use Objects\Context;
|
use Objects\Context;
|
||||||
|
|
||||||
@ -17,7 +18,9 @@ class Settings {
|
|||||||
// settings
|
// settings
|
||||||
private string $siteName;
|
private string $siteName;
|
||||||
private string $baseUrl;
|
private string $baseUrl;
|
||||||
private string $jwtSecret;
|
private string $jwtPublicKey;
|
||||||
|
private string $jwtSecretKey;
|
||||||
|
private string $jwtAlgorithm;
|
||||||
private bool $registrationAllowed;
|
private bool $registrationAllowed;
|
||||||
private bool $recaptchaEnabled;
|
private bool $recaptchaEnabled;
|
||||||
private bool $mailEnabled;
|
private bool $mailEnabled;
|
||||||
@ -27,9 +30,19 @@ class Settings {
|
|||||||
private string $mailFooter;
|
private string $mailFooter;
|
||||||
private array $allowedExtensions;
|
private array $allowedExtensions;
|
||||||
|
|
||||||
public function getJwtKey(): \Firebase\JWT\Key {
|
//
|
||||||
// TODO: allow the use of other JWT algorithms (e.g. RS256)
|
private Logger $logger;
|
||||||
return new \Firebase\JWT\Key($this->jwtSecret, "HS256");
|
|
||||||
|
public function __construct() {
|
||||||
|
$this->logger = new Logger("Settings");
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getJwtPublicKey(): \Firebase\JWT\Key {
|
||||||
|
return new \Firebase\JWT\Key($this->jwtPublicKey ?? $this->jwtSecretKey, $this->jwtAlgorithm);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function getJwtSecretKey(): \Firebase\JWT\Key {
|
||||||
|
return new \Firebase\JWT\Key($this->jwtSecretKey, $this->jwtAlgorithm);
|
||||||
}
|
}
|
||||||
|
|
||||||
public function isInstalled(): bool {
|
public function isInstalled(): bool {
|
||||||
@ -39,26 +52,74 @@ class Settings {
|
|||||||
public static function loadDefaults(): Settings {
|
public static function loadDefaults(): Settings {
|
||||||
$hostname = $_SERVER["SERVER_NAME"] ?? "localhost";
|
$hostname = $_SERVER["SERVER_NAME"] ?? "localhost";
|
||||||
$protocol = getProtocol();
|
$protocol = getProtocol();
|
||||||
$jwt = generateRandomString(32);
|
|
||||||
|
|
||||||
$settings = new Settings();
|
$settings = new Settings();
|
||||||
|
|
||||||
|
// General
|
||||||
$settings->siteName = "WebBase";
|
$settings->siteName = "WebBase";
|
||||||
$settings->baseUrl = "$protocol://$hostname";
|
$settings->baseUrl = "$protocol://$hostname";
|
||||||
$settings->jwtSecret = $jwt;
|
$settings->allowedExtensions = ['png', 'jpg', 'jpeg', 'gif', 'htm', 'html'];
|
||||||
$settings->installationComplete = false;
|
$settings->installationComplete = false;
|
||||||
$settings->registrationAllowed = false;
|
$settings->registrationAllowed = false;
|
||||||
|
|
||||||
|
// JWT
|
||||||
|
$settings->jwtSecretKey = null;
|
||||||
|
$settings->jwtPublicKey = null;
|
||||||
|
$settings->jwtAlgorithm = "HS256";
|
||||||
|
|
||||||
|
// Recaptcha
|
||||||
|
$settings->recaptchaEnabled = false;
|
||||||
$settings->recaptchaPublicKey = "";
|
$settings->recaptchaPublicKey = "";
|
||||||
$settings->recaptchaPrivateKey = "";
|
$settings->recaptchaPrivateKey = "";
|
||||||
$settings->recaptchaEnabled = false;
|
|
||||||
|
// Mail
|
||||||
$settings->mailEnabled = false;
|
$settings->mailEnabled = false;
|
||||||
$settings->mailSender = "webmaster@localhost";
|
$settings->mailSender = "webmaster@localhost";
|
||||||
$settings->mailFooter = "";
|
$settings->mailFooter = "";
|
||||||
$settings->allowedExtensions = ['png', 'jpg', 'jpeg', 'gif', 'htm', 'html'];
|
|
||||||
|
|
||||||
return $settings;
|
return $settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function generateJwtKey(string $algorithm = null): bool {
|
||||||
|
$this->jwtAlgorithm = $algorithm ?? $this->jwtAlgorithm;
|
||||||
|
|
||||||
|
// TODO: key encryption necessary?
|
||||||
|
if (in_array($this->jwtAlgorithm, ["HS256", "HS384", "HS512"])) {
|
||||||
|
$this->jwtSecretKey = generateRandomString(32);
|
||||||
|
$this->jwtPublicKey = null;
|
||||||
|
} else if (in_array($this->jwtAlgorithm, ["RS256", "RS384", "RS512"])) {
|
||||||
|
$bits = intval(substr($this->jwtAlgorithm, 2));
|
||||||
|
$private_key = openssl_pkey_new(["private_key_bits" => $bits]);
|
||||||
|
$this->jwtPublicKey = openssl_pkey_get_details($private_key)['key'];
|
||||||
|
openssl_pkey_export($private_key, $this->jwtSecretKey);
|
||||||
|
} else if (in_array($this->jwtAlgorithm, ["ES256", "ES384"])) {
|
||||||
|
// $ec = new \Elliptic\EC('secp256k1'); ??
|
||||||
|
$this->logger->error("JWT algorithm: '$this->jwtAlgorithm' is currently not supported.");
|
||||||
|
return false;
|
||||||
|
} else if ($this->jwtAlgorithm == "EdDSA") {
|
||||||
|
$keyPair = sodium_crypto_sign_keypair();
|
||||||
|
$this->jwtSecretKey = base64_encode(sodium_crypto_sign_secretkey($keyPair));
|
||||||
|
$this->jwtPublicKey = base64_encode(sodium_crypto_sign_publickey($keyPair));
|
||||||
|
} else {
|
||||||
|
$this->logger->error("Invalid JWT algorithm: '$this->jwtAlgorithm', expected one of: " .
|
||||||
|
implode(",", array_keys(\Firebase\JWT\JWT::$supported_algs)));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function saveJwtKey(Context $context) {
|
||||||
|
$req = new \Api\Settings\Set($context);
|
||||||
|
$req->execute(array("settings" => array(
|
||||||
|
"jwt_secret_key" => $this->jwtSecretKey,
|
||||||
|
"jwt_public_key" => $this->jwtSecretKey,
|
||||||
|
"jwt_algorithm" => $this->jwtAlgorithm,
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
|
||||||
public function loadFromDatabase(Context $context): bool {
|
public function loadFromDatabase(Context $context): bool {
|
||||||
|
$this->logger = new Logger("Settings", $context->getSQL());
|
||||||
$req = new \Api\Settings\Get($context);
|
$req = new \Api\Settings\Get($context);
|
||||||
$success = $req->execute();
|
$success = $req->execute();
|
||||||
|
|
||||||
@ -68,7 +129,9 @@ class Settings {
|
|||||||
$this->baseUrl = $result["base_url"] ?? $this->baseUrl;
|
$this->baseUrl = $result["base_url"] ?? $this->baseUrl;
|
||||||
$this->registrationAllowed = $result["user_registration_enabled"] ?? $this->registrationAllowed;
|
$this->registrationAllowed = $result["user_registration_enabled"] ?? $this->registrationAllowed;
|
||||||
$this->installationComplete = $result["installation_completed"] ?? $this->installationComplete;
|
$this->installationComplete = $result["installation_completed"] ?? $this->installationComplete;
|
||||||
$this->jwtSecret = $result["jwt_secret"] ?? $this->jwtSecret;
|
$this->jwtSecretKey = $result["jwt_secret_key"] ?? $this->jwtSecretKey;
|
||||||
|
$this->jwtPublicKey = $result["jwt_public_key"] ?? $this->jwtPublicKey;
|
||||||
|
$this->jwtAlgorithm = $result["jwt_algorithm"] ?? $this->jwtAlgorithm;
|
||||||
$this->recaptchaEnabled = $result["recaptcha_enabled"] ?? $this->recaptchaEnabled;
|
$this->recaptchaEnabled = $result["recaptcha_enabled"] ?? $this->recaptchaEnabled;
|
||||||
$this->recaptchaPublicKey = $result["recaptcha_public_key"] ?? $this->recaptchaPublicKey;
|
$this->recaptchaPublicKey = $result["recaptcha_public_key"] ?? $this->recaptchaPublicKey;
|
||||||
$this->recaptchaPrivateKey = $result["recaptcha_private_key"] ?? $this->recaptchaPrivateKey;
|
$this->recaptchaPrivateKey = $result["recaptcha_private_key"] ?? $this->recaptchaPrivateKey;
|
||||||
@ -77,11 +140,10 @@ class Settings {
|
|||||||
$this->mailFooter = $result["mail_footer"] ?? $this->mailFooter;
|
$this->mailFooter = $result["mail_footer"] ?? $this->mailFooter;
|
||||||
$this->allowedExtensions = explode(",", $result["allowed_extensions"] ?? strtolower(implode(",", $this->allowedExtensions)));
|
$this->allowedExtensions = explode(",", $result["allowed_extensions"] ?? strtolower(implode(",", $this->allowedExtensions)));
|
||||||
|
|
||||||
if (!isset($result["jwt_secret"])) {
|
if (!isset($result["jwt_secret_key"])) {
|
||||||
$req = new \Api\Settings\Set($context);
|
if ($this->generateJwtKey()) {
|
||||||
$req->execute(array("settings" => array(
|
$this->saveJwtKey($context);
|
||||||
"jwt_secret" => $this->jwtSecret
|
}
|
||||||
)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -93,7 +155,9 @@ class Settings {
|
|||||||
->addRow("base_url", $this->baseUrl, false, false)
|
->addRow("base_url", $this->baseUrl, false, false)
|
||||||
->addRow("user_registration_enabled", $this->registrationAllowed ? "1" : "0", false, false)
|
->addRow("user_registration_enabled", $this->registrationAllowed ? "1" : "0", false, false)
|
||||||
->addRow("installation_completed", $this->installationComplete ? "1" : "0", true, true)
|
->addRow("installation_completed", $this->installationComplete ? "1" : "0", true, true)
|
||||||
->addRow("jwt_secret", $this->jwtSecret, true, true)
|
->addRow("jwt_secret_key", $this->jwtSecretKey, true, false)
|
||||||
|
->addRow("jwt_public_key", $this->jwtPublicKey, false, false)
|
||||||
|
->addRow("jwt_algorithm", $this->jwtAlgorithm, false, false)
|
||||||
->addRow("recaptcha_enabled", $this->recaptchaEnabled ? "1" : "0", false, false)
|
->addRow("recaptcha_enabled", $this->recaptchaEnabled ? "1" : "0", false, false)
|
||||||
->addRow("recaptcha_public_key", $this->recaptchaPublicKey, false, false)
|
->addRow("recaptcha_public_key", $this->recaptchaPublicKey, false, false)
|
||||||
->addRow("recaptcha_private_key", $this->recaptchaPrivateKey, true, false)
|
->addRow("recaptcha_private_key", $this->recaptchaPrivateKey, true, false)
|
||||||
|
@ -65,7 +65,7 @@ class MySQL extends SQL {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
mysqli_set_charset($this->connection, $this->connectionData->getProperty('encoding', 'UTF-8'));
|
mysqli_set_charset($this->connection, $this->connectionData->getProperty('encoding', 'UTF8'));
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,7 +99,7 @@ class Context {
|
|||||||
try {
|
try {
|
||||||
$token = $_COOKIE['session'];
|
$token = $_COOKIE['session'];
|
||||||
$settings = $this->configuration->getSettings();
|
$settings = $this->configuration->getSettings();
|
||||||
$decoded = (array)JWT::decode($token, $settings->getJwtKey());
|
$decoded = (array)JWT::decode($token, $settings->getJwtSecretKey());
|
||||||
if (!is_null($decoded)) {
|
if (!is_null($decoded)) {
|
||||||
$userId = ($decoded['userId'] ?? NULL);
|
$userId = ($decoded['userId'] ?? NULL);
|
||||||
$sessionId = ($decoded['sessionId'] ?? NULL);
|
$sessionId = ($decoded['sessionId'] ?? NULL);
|
||||||
|
@ -74,8 +74,8 @@ class Session extends DatabaseEntity {
|
|||||||
$this->updateMetaData();
|
$this->updateMetaData();
|
||||||
$settings = $this->context->getSettings();
|
$settings = $this->context->getSettings();
|
||||||
$token = ['userId' => $this->user->getId(), 'sessionId' => $this->getId()];
|
$token = ['userId' => $this->user->getId(), 'sessionId' => $this->getId()];
|
||||||
$jwtKey = $settings->getJwtKey();
|
$jwtPublicKey = $settings->getJwtPublicKey();
|
||||||
return JWT::encode($token, $jwtKey->getKeyMaterial(), $jwtKey->getAlgorithm());
|
return JWT::encode($token, $jwtPublicKey->getKeyMaterial(), $jwtPublicKey->getAlgorithm());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function sendCookie(string $domain) {
|
public function sendCookie(string $domain) {
|
||||||
|
Loading…
Reference in New Issue
Block a user