refactor: migrate JWT storage to secure storage, update assets, and enhance login verification logic.

This commit is contained in:
Hamza-Ayed
2026-08-06 22:54:52 +03:00
parent 52101e650c
commit 97471fd2bd
12 changed files with 239 additions and 138 deletions
+63 -29
View File
@@ -53,47 +53,81 @@ try {
$stmt->execute([':id' => $id]);
$driver = $stmt->fetch();
if (!$driver || empty($driver['password'])) {
if (!$driver) {
unauthorizedDriver();
}
$decPhone = !empty($driver['phone']) ? $encryptionHelper->decryptData($driver['phone']) : null;
$decNat = !empty($driver['national_number']) ? $encryptionHelper->decryptData($driver['national_number']) : null;
// ── مسار السائقين المسجلين عبر OTP (بدون password في DB) ──
if (empty($driver['password'])) {
// التحقق من هوية السائق عبر fingerprint المخزن في driverToken
if (empty($fingerprint)) {
securityLog("LoginDriver(OTP): no fingerprint sent", [
'driver_id' => $driver['id'],
]);
unauthorizedDriver();
}
if (empty($decPhone)) {
securityLog("LoginDriver failed: phone decryption returned null", [
'driver_id' => $driver['id'] ?? 'unknown',
]);
unauthorizedDriver();
}
$stmtFp = $con->prepare('SELECT fingerPrint FROM driverToken WHERE captain_id = :id LIMIT 1');
$stmtFp->execute([':id' => $driver['id']]);
$fpRow = $stmtFp->fetch();
// ── المحاولة الأولى: طريقة جديدة (قيم خام) ─────────────
$newParts = [
$driver['id'],
trim($decPhone),
];
if (!empty($decNat)) {
$newParts[] = trim($decNat);
}
$newString = implode('|', $newParts);
$newSecret = hash_hmac('sha256', $newString, $pepper, true);
if (!$fpRow || empty($fpRow['fingerPrint'])) {
securityLog("LoginDriver(OTP): no stored fingerprint found", [
'driver_id' => $driver['id'],
]);
unauthorizedDriver();
}
if (password_verify($newSecret, $driver['password'])) {
// ✅ صح - طريقة جديدة
$fpPepper = getenv('FP_PEPPER') ?: '';
$expectedFp = !empty($fpPepper) ? hash('sha256', $fingerprint . $fpPepper) : $fingerprint;
if (!hash_equals($fpRow['fingerPrint'], $expectedFp)) {
securityLog("LoginDriver(OTP): fingerprint mismatch", [
'driver_id' => $driver['id'],
]);
unauthorizedDriver();
}
// ✅ تم التحقق عبر fingerprint — نتابع لتوليد JWT
} else {
// ── المحاولة الثانية: طريقة قديمة (قيم مشفرة) للتوافق ─
$oldParts = [
// ── المسار التقليدي: التحقق عبر password + HMAC ──────────
$decPhone = !empty($driver['phone']) ? $encryptionHelper->decryptData($driver['phone']) : null;
$decNat = !empty($driver['national_number']) ? $encryptionHelper->decryptData($driver['national_number']) : null;
if (empty($decPhone)) {
securityLog("LoginDriver failed: phone decryption returned null", [
'driver_id' => $driver['id'] ?? 'unknown',
]);
unauthorizedDriver();
}
// ── المحاولة الأولى: طريقة جديدة (قيم خام) ─────────────
$newParts = [
$driver['id'],
$encryptionHelper->encryptData(trim($decPhone)),
trim($decPhone),
];
if (!empty($decNat)) {
$oldParts[] = $encryptionHelper->encryptData(trim($decNat));
$newParts[] = trim($decNat);
}
$oldString = implode('|', $oldParts);
$oldSecret = hash_hmac('sha256', $oldString, $pepper, true);
$newString = implode('|', $newParts);
$newSecret = hash_hmac('sha256', $newString, $pepper, true);
if (!password_verify($oldSecret, $driver['password'])) {
unauthorizedDriver();
if (password_verify($newSecret, $driver['password'])) {
// ✅ صح - طريقة جديدة
} else {
// ── المحاولة الثانية: طريقة قديمة (قيم مشفرة) للتوافق ─
$oldParts = [
$driver['id'],
$encryptionHelper->encryptData(trim($decPhone)),
];
if (!empty($decNat)) {
$oldParts[] = $encryptionHelper->encryptData(trim($decNat));
}
$oldString = implode('|', $oldParts);
$oldSecret = hash_hmac('sha256', $oldString, $pepper, true);
if (!password_verify($oldSecret, $driver['password'])) {
unauthorizedDriver();
}
}
}