commit
This commit is contained in:
105
inc/AuthService.php
Normal file
105
inc/AuthService.php
Normal file
@@ -0,0 +1,105 @@
|
||||
<?php
|
||||
declare(strict_types=1);
|
||||
|
||||
// -----------------------------------------------------------------
|
||||
// AuthService.php: Kapselt die gesamte Authentifizierungslogik.
|
||||
// -----------------------------------------------------------------
|
||||
|
||||
class AuthService
|
||||
{
|
||||
private array $conf;
|
||||
private PDO $pdo;
|
||||
|
||||
// Abhängigkeiten (Konfiguration und PDO) werden per Konstruktor übergeben
|
||||
public function __construct(array $conf, PDO $pdo)
|
||||
{
|
||||
$this->conf = $conf;
|
||||
$this->pdo = $pdo;
|
||||
}
|
||||
|
||||
// --- Private Utility Methoden ---
|
||||
|
||||
private function fail(string $msg, $detail = null, int $code = 400): void
|
||||
{
|
||||
// Wir müssen hier direkt antworten, da wir das Fail-Verhalten des Kernels benötigen.
|
||||
// Im ApiKernel werden wir die respond/fail-Methoden als public lassen,
|
||||
// um sie hier injizieren zu können, oder wir lassen sie hier im Global Scope
|
||||
// (WENN Sie die ursprünglichen globalen Funktionen respond/fail wieder zulassen).
|
||||
// Für eine saubere Kapselung injizieren wir die Respond-Logik.
|
||||
// HIER verwenden wir eine einfache JSON-Antwort, da die fail-Methode
|
||||
// normalerweise den gesamten Kernel stoppt. Wir nutzen exit.
|
||||
|
||||
http_response_code($code);
|
||||
echo json_encode(['ok'=>false,'error'=>$msg,'detail'=>$detail], JSON_UNESCAPED_UNICODE|JSON_UNESCAPED_SLASHES);
|
||||
exit;
|
||||
}
|
||||
|
||||
private function verifyPassword(string $input, string $stored, array $authDbConf): bool
|
||||
{
|
||||
if (preg_match('~^\$2[aby]\$~', $stored) || strpos($stored, '$argon2') === 0) return password_verify($input, $stored);
|
||||
$legacy = strtolower($authDbConf['legacy'] ?? '');
|
||||
if ($legacy === 'md5') return hash_equals($stored, md5($input));
|
||||
if ($legacy === 'sha1') return hash_equals($stored, sha1($input));
|
||||
if (password_get_info($stored)['algo'] !== 0) return password_verify($input, $stored);
|
||||
return hash_equals($stored, $input);
|
||||
}
|
||||
|
||||
// --- Public Service Methoden ---
|
||||
|
||||
public function requireAuth(): array
|
||||
{
|
||||
if (empty($_SESSION['auth'])) $this->fail('Not authenticated', null, 401);
|
||||
return $_SESSION['auth'];
|
||||
}
|
||||
|
||||
public function logout(): bool
|
||||
{
|
||||
$_SESSION = [];
|
||||
if (session_id() !== '') session_destroy();
|
||||
return true;
|
||||
}
|
||||
|
||||
public function login(array $in): array
|
||||
{
|
||||
$authDb = $this->conf['auth']['db'] ?? [];
|
||||
$colUser = $authDb['col_user'] ?? 'email';
|
||||
$colPass = $authDb['col_pass'] ?? 'password';
|
||||
$colName = $authDb['col_name'] ?? 'name';
|
||||
$colId = $authDb['col_id'] ?? 'id';
|
||||
$colStatus = $authDb['col_status']?? null;
|
||||
$activeValues = $authDb['active_values'] ?? ['active','1',1];
|
||||
$table = $authDb['table'] ?? 'emailtemplate_users';
|
||||
|
||||
$identifier = trim((string)($in['username'] ?? $in['user'] ?? $in['email'] ?? $in['login'] ?? ''));
|
||||
$password = (string)($in['password'] ?? $in['pass'] ?? $in['pwd'] ?? '');
|
||||
|
||||
if ($identifier === '' || $password === '') $this->fail('username/password required', null, 422);
|
||||
|
||||
$stmt = $this->pdo->prepare("SELECT * FROM `$table` WHERE `$colUser` = :u LIMIT 1");
|
||||
$stmt->execute([':u'=>$identifier]);
|
||||
$row = $stmt->fetch();
|
||||
|
||||
if (!$row) $this->fail('Invalid credentials', null, 401);
|
||||
|
||||
if ($colStatus && isset($row[$colStatus])) {
|
||||
if (!in_array($row[$colStatus], $activeValues, true)) {
|
||||
$this->fail('Account inactive', null, 403);
|
||||
}
|
||||
}
|
||||
|
||||
$stored = (string)($row[$colPass] ?? '');
|
||||
if ($stored === '' || !$this->verifyPassword($password, $stored, $authDb)) {
|
||||
$this->fail('Invalid credentials', null, 401);
|
||||
}
|
||||
|
||||
$_SESSION['auth'] = [
|
||||
'id' => $row[$colId] ?? null,
|
||||
'name' => $row[$colName] ?? ($row[$colUser] ?? $identifier),
|
||||
'email' => $row[$colUser] ?? $identifier,
|
||||
'at' => time(),
|
||||
];
|
||||
|
||||
$token = base64_encode(hash('sha256', ($_SESSION['auth']['id'] ?? $identifier).'|'.session_id(), true));
|
||||
return ['user'=>$_SESSION['auth'], 'token'=>$token];
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user