Update: 2026-08-06 22:54:35
This commit is contained in:
@@ -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>
|
||||||
Reference in New Issue
Block a user