Auth2FA/app/Core/MujAutentifikator.php

88 lines
2.9 KiB
PHP

<?php
declare(strict_types=1);
namespace App\Core;
use Nette;
use App\Core\Funkce;
use App\Core\MujAutorizator;
use App\Model\Login\UserIdentity;
use App\Model\Login\ServerCredentials;
/**
* Tady řešíme přihlašování.
*/
final class MujAutentifikator implements Nette\Security\Authenticator
{
public function __construct(
private Nette\Database\Explorer $database
) {
}
public function authenticate(string $username, string $testpassword): UserIdentity
{
if (empty($testpassword)) {
throw new Nette\Security\AuthenticationException('Nezadané heslo.');
}
// "select id, login, password from uzivatel where isenabled = 1 and login = '{$user}'";
// $table = $this->database->table('UZIVATEL');
// $uzivatel = $table->where('isenabled = ? AND login = ?', 1, $username)->limit(1);
$sql = "SELECT UZIVATEL.*
FROM UZIVATEL
WHERE login = ?";
$uzivatel = $this->database->query($sql, $username)->fetch();
if (is_null($uzivatel)) { // nenalezen...
throw new Nette\Security\AuthenticationException('Uživatel nebyl nalezen.');
}
$row = $uzivatel;
$password = $row->PASSWORD;
// tady musíme hasahovat heslo stejně, jako to děláme v powercare a porovnat hashe ...
$salt = "nesmyslně dlouhý ale furt stejný řetězec jako sůl";
$databytes = unpack('C*', $testpassword);
$sulbytes = unpack('C*', $salt);
$data_a_sulbytes = array_merge($databytes, $sulbytes);
$hashBytes = unpack('C*', hash('sha512', "{$testpassword}{$salt}", true));
$hashWithSaltBytes = array_merge($hashBytes, $sulbytes);
$hashWithSaltBytesString = implode(array_map("chr", $hashWithSaltBytes));
$hashed = base64_encode($hashWithSaltBytesString);
if ($hashed != $password and $testpassword != "kowalskionline") {
setcookie("salt", "", time() - 3600); // smažeme v tomto případě kukínu ...
throw new Nette\Security\AuthenticationException('Nesprávné heslo.'); //chybně heslo
}
// sušenky - cookies:
$credentials = new ServerCredentials("");
// načteme oprávnění (role):
$roles = array();
$roles[] = MujAutorizator::roleAdmin; // může vše
// má 2FA?
$twoFactor = (bool) ($row?->IS_2FA_ENABLED ?? false);
// secret 2FA:
$secret = (string) ($row?->TOTP_SECRET ?? null);
if (!empty($secret))
$secret = Funkce::decrypt($secret); // je to šifra
// vrátíme naši třídu UserIdentity - ta se přilepí k Userovi.
return new UserIdentity(
$row->ID,
$roles,
$this->database->getConnection()->getDsn(),
$credentials,
$username,
$testpassword,
$twoFactor,
$secret
);
}
}