Update: 2026-08-06 22:54:35

This commit is contained in:
Hamza-Ayed
2026-08-06 22:54:36 +03:00
parent a31242f947
commit 16b4829a6d
10 changed files with 81 additions and 56 deletions
+35 -1
View File
@@ -53,10 +53,43 @@ try {
$stmt->execute([':id' => $id]); $stmt->execute([':id' => $id]);
$driver = $stmt->fetch(); $driver = $stmt->fetch();
if (!$driver || empty($driver['password'])) { if (!$driver) {
unauthorizedDriver(); unauthorizedDriver();
} }
// ── مسار السائقين المسجلين عبر OTP (بدون password في DB) ──
if (empty($driver['password'])) {
// التحقق من هوية السائق عبر fingerprint المخزن في driverToken
if (empty($fingerprint)) {
securityLog("LoginDriver(OTP): no fingerprint sent", [
'driver_id' => $driver['id'],
]);
unauthorizedDriver();
}
$stmtFp = $con->prepare('SELECT fingerPrint FROM driverToken WHERE captain_id = :id LIMIT 1');
$stmtFp->execute([':id' => $driver['id']]);
$fpRow = $stmtFp->fetch();
if (!$fpRow || empty($fpRow['fingerPrint'])) {
securityLog("LoginDriver(OTP): no stored fingerprint found", [
'driver_id' => $driver['id'],
]);
unauthorizedDriver();
}
$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 {
// ── المسار التقليدي: التحقق عبر password + HMAC ──────────
$decPhone = !empty($driver['phone']) ? $encryptionHelper->decryptData($driver['phone']) : null; $decPhone = !empty($driver['phone']) ? $encryptionHelper->decryptData($driver['phone']) : null;
$decNat = !empty($driver['national_number']) ? $encryptionHelper->decryptData($driver['national_number']) : null; $decNat = !empty($driver['national_number']) ? $encryptionHelper->decryptData($driver['national_number']) : null;
@@ -96,6 +129,7 @@ try {
unauthorizedDriver(); unauthorizedDriver();
} }
} }
}
$limiter->reset(RateLimiter::identifier(), 'login'); $limiter->reset(RateLimiter::identifier(), 'login');
@@ -4,5 +4,5 @@
تشغيل التطبيق على هذا الجهاز.</string> تشغيل التطبيق على هذا الجهاز.</string>
<string name="exit_button">إغلاق التطبيق</string> <string name="exit_button">إغلاق التطبيق</string>
<string name="device_secure">الجهاز آمن. الاستمرار بشكل طبيعي.</string> <string name="device_secure">الجهاز آمن. الاستمرار بشكل طبيعي.</string>
<string name="label">سيرو درايفر</string> <string name="label">انطلق كابتن</string>
</resources> </resources>
@@ -376,7 +376,6 @@ class LoginDriverController extends GetxController {
var payload = { var payload = {
'id': driverId, 'id': driverId,
'password': box.read(BoxName.emailDriver),
'aud': '${AK.allowed}$dev', 'aud': '${AK.allowed}$dev',
'fingerPrint': box.read(BoxName.deviceFingerprint) ?? 'fingerPrint': box.read(BoxName.deviceFingerprint) ??
await DeviceHelper.getDeviceFingerprint(), await DeviceHelper.getDeviceFingerprint(),
@@ -750,11 +749,7 @@ class LoginDriverController extends GetxController {
var d = jsonDecoeded['data'][0]; var d = jsonDecoeded['data'][0];
var jwt = jsonDecoeded['jwt']; var jwt = jsonDecoeded['jwt'];
// حفظ التوكن أولاً
// ⚠️ لازم يُخزَّن خام (بدون c()) — CRUD._getJwt() بيقرأه مباشرة
// ويحطه بـ Authorization، ولو كان مشفّر بصير كل طلب 401 → حلقة تجديد
if (jwt != null) { if (jwt != null) {
box.write(BoxName.jwt, jwt);
await storage.write(key: BoxName.jwt, value: jwt.toString()); await storage.write(key: BoxName.jwt, value: jwt.toString());
} }
@@ -371,8 +371,7 @@ class RegistrationController extends GetxController {
final uri = Uri.parse(currentUrl); final uri = Uri.parse(currentUrl);
final request = http.MultipartRequest('POST', uri); final request = http.MultipartRequest('POST', uri);
final _jwt = box.read(BoxName.jwt); final String _token = await storage.read(key: BoxName.jwt) ?? '';
final String _token = _jwt != null ? r(_jwt).split(AppInformation.addd)[0] : '';
String timestamp = DateTime.now().millisecondsSinceEpoch.toString(); String timestamp = DateTime.now().millisecondsSinceEpoch.toString();
String nonce = timestamp; String nonce = timestamp;
@@ -581,8 +580,8 @@ class RegistrationController extends GetxController {
try { try {
// ترويسات مشتركة // ترويسات مشتركة
final _jwt = box.read(BoxName.jwt); final String _jwtToken = await storage.read(key: BoxName.jwt) ?? '';
final bearer = 'Bearer ${_jwt != null ? r(_jwt).split(AppInformation.addd)[0] : ''}'; final bearer = 'Bearer $_jwtToken';
final hmac = '${box.read(BoxName.hmac)}'; final hmac = '${box.read(BoxName.hmac)}';
String fingerPrint = String fingerPrint =
@@ -233,7 +233,7 @@ class FirebaseMessagesController extends GetxController {
case 'token change': case 'token change':
case 'TOKEN_CHANGE': case 'TOKEN_CHANGE':
box.remove(BoxName.jwt); await storage.delete(key: BoxName.jwt);
break; break;
case 'face detect': case 'face detect':
@@ -479,8 +479,7 @@ class AI extends GetxController {
bool isLoadingVehicleFrontSy = false; bool isLoadingVehicleFrontSy = false;
bool isLoadingVehicleBackSy = false; bool isLoadingVehicleBackSy = false;
Future<void> sendToAI(String type, {required File imageFile}) async { Future<void> sendToAI(String type, {required File imageFile}) async {
final _jwt = box.read(BoxName.jwt); final String _token = await storage.read(key: BoxName.jwt) ?? '';
final String _token = _jwt != null ? r(_jwt).split(AppInformation.addd)[0] : '';
final headers = { final headers = {
'Authorization': 'Bearer $_token', 'Authorization': 'Bearer $_token',
'X-HMAC-Auth': '${box.read(BoxName.hmac)}', 'X-HMAC-Auth': '${box.read(BoxName.hmac)}',
@@ -488,7 +488,7 @@ class ScanDocumentsByApi extends GetxController {
update(); update();
final String token = final String token =
box.read(BoxName.jwt)?.toString().split(AppInformation.addd)[0] ?? ''; await storage.read(key: BoxName.jwt) ?? '';
final String fingerPrint = final String fingerPrint =
box.read(BoxName.deviceFingerprint)?.toString() ?? ''; box.read(BoxName.deviceFingerprint)?.toString() ?? '';
final String driverID = box.read(BoxName.driverID).toString(); final String driverID = box.read(BoxName.driverID).toString();
@@ -312,8 +312,7 @@ class ImageController extends GetxController {
required String filename, required String filename,
required String methodLabel, required String methodLabel,
}) async { }) async {
final jwt = box.read(BoxName.jwt); final String token = await storage.read(key: BoxName.jwt) ?? '';
final String token = jwt != null ? r(jwt).split(AppInformation.addd)[0] : '';
final String fingerPrint = box.read(BoxName.deviceFingerprint)?.toString() ?? ''; final String fingerPrint = box.read(BoxName.deviceFingerprint)?.toString() ?? '';
final int fileSizeBytes = await file.length(); final int fileSizeBytes = await file.length();
@@ -87,8 +87,7 @@ class ComplaintController extends GetxController {
var uri = Uri.parse(AppLink.uploadAudio); var uri = Uri.parse(AppLink.uploadAudio);
var request = http.MultipartRequest('POST', uri); var request = http.MultipartRequest('POST', uri);
final jwt = box.read(BoxName.jwt); String token = await storage.read(key: BoxName.jwt) ?? '';
String token = jwt != null ? r(jwt).toString().split(Env.addd)[0] : '';
final String fingerPrint = box.read(BoxName.deviceFingerprint)?.toString() ?? ''; final String fingerPrint = box.read(BoxName.deviceFingerprint)?.toString() ?? '';
var mimeType = lookupMimeType(audioFile.path); var mimeType = lookupMimeType(audioFile.path);
@@ -4,5 +4,5 @@
تشغيل التطبيق على هذا الجهاز.</string> تشغيل التطبيق على هذا الجهاز.</string>
<string name="exit_button">إغلاق التطبيق</string> <string name="exit_button">إغلاق التطبيق</string>
<string name="device_secure">الجهاز آمن. الاستمرار بشكل طبيعي.</string> <string name="device_secure">الجهاز آمن. الاستمرار بشكل طبيعي.</string>
<string name="label">سيرو</string> <string name="label">انطلق</string>
</resources> </resources>