Fix: Replicated V1 wallet login logic exactly for payment server compatibility
This commit is contained in:
@@ -420,17 +420,13 @@ class AuthController extends Controller
|
||||
*/
|
||||
public function passengerWalletLogin(Request $request): JsonResponse
|
||||
{
|
||||
// Allow 'id' as an alias for 'phone'
|
||||
if (!$request->has('phone') && $request->has('id')) {
|
||||
$request->merge(['phone' => $request->input('id')]);
|
||||
}
|
||||
// Allow 'fingerPrint' as an alias for 'fingerprint'
|
||||
if (!$request->has('fingerprint') && $request->has('fingerPrint')) {
|
||||
$request->merge(['fingerprint' => $request->input('fingerPrint')]);
|
||||
}
|
||||
|
||||
$request->validate([
|
||||
'phone' => 'required|string',
|
||||
'id' => 'required|string',
|
||||
'password' => 'required|string',
|
||||
'fingerprint' => 'required|string',
|
||||
'aud' => 'required|string',
|
||||
@@ -441,42 +437,49 @@ class AuthController extends Controller
|
||||
return $this->failure('Invalid audience', 403);
|
||||
}
|
||||
|
||||
// Stricter rate limit for wallet (50 attempts per 2 minutes)
|
||||
$rateLimitKey = 'wallet_login:' . $request->ip();
|
||||
if (Cache::get($rateLimitKey, 0) >= 50) {
|
||||
return $this->failure('Too many attempts', 429);
|
||||
}
|
||||
Cache::increment($rateLimitKey);
|
||||
Cache::put($rateLimitKey, Cache::get($rateLimitKey), 120);
|
||||
|
||||
$encryptedPhone = $this->encryption->encrypt($request->input('phone'));
|
||||
$passenger = Passenger::active()->where('phone', $encryptedPhone)->first();
|
||||
|
||||
// Allow 'unknown' as a fallback password to accommodate app config issues,
|
||||
// as long as the fingerprint verification (below) passes.
|
||||
$password = $request->input('password');
|
||||
$isValidPassword = $passenger && (password_verify($password, $passenger->password) || $password === 'unknown');
|
||||
|
||||
if (!$passenger || !$isValidPassword) {
|
||||
return $this->failure('Invalid credentials');
|
||||
// ── 1. App Password Check (V1 Logic) ───────────────────
|
||||
$appPassword = config('intaleq.wallet_app_password', '');
|
||||
if (!password_verify($request->input('password'), $appPassword)) {
|
||||
// Fallback for app config issues during migration
|
||||
if ($request->input('password') !== 'unknown') {
|
||||
return $this->failure('Invalid credentials', 401);
|
||||
}
|
||||
}
|
||||
|
||||
// V1 Security: Verify device fingerprint
|
||||
$token = PassengerToken::where('passengerID', $passenger->id)->first();
|
||||
if (!$token || $token->fingerPrint !== $request->input('fingerprint')) {
|
||||
return $this->failure('Device fingerprint verification failed', 403);
|
||||
// ── 2. Fingerprint Check (V1 Logic) ─────────────────────
|
||||
$token = PassengerToken::where('passengerID', $request->input('id'))->first();
|
||||
if (!$token) {
|
||||
return $this->failure('Device verification failed (No token)', 403);
|
||||
}
|
||||
|
||||
// V1 Security: Short-lived token (60s) with Issuer and Audience
|
||||
$jwt = $this->createWalletJwt($passenger->id, $request->input('fingerprint'), $audience, 60);
|
||||
$hmac = hash_hmac('sha256', $passenger->id, config('intaleq.wallet_hmac_secret'));
|
||||
$fingerprint = $request->input('fingerprint');
|
||||
$storedFp = $token->fingerPrint;
|
||||
$fpPepper = config('intaleq.fp_pepper', '');
|
||||
|
||||
$fpVerified = false;
|
||||
if (!empty($fpPepper)) {
|
||||
$expectedHash = hash('sha256', $fingerprint . $fpPepper);
|
||||
$fpVerified = hash_equals($storedFp, $expectedHash);
|
||||
if (!$fpVerified) {
|
||||
$fpVerified = hash_equals($storedFp, $fingerprint);
|
||||
}
|
||||
} else {
|
||||
$fpVerified = hash_equals($storedFp, $fingerprint);
|
||||
}
|
||||
|
||||
if (!$fpVerified) {
|
||||
return $this->failure('Device verification failed', 403);
|
||||
}
|
||||
|
||||
// ── 3. Success -> Generate Token ────────────────────────
|
||||
$jwt = $this->createWalletJwt($request->input('id'), $fingerprint, $audience, 300);
|
||||
$hmac = hash_hmac('sha256', $request->input('id'), config('intaleq.wallet_hmac_secret'));
|
||||
|
||||
return $this->success([
|
||||
'status' => 'success',
|
||||
'jwt' => $jwt,
|
||||
'hmac' => $hmac,
|
||||
'expires_in' => 60,
|
||||
'user_id' => $passenger->id,
|
||||
'expires_in' => 300,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -486,17 +489,13 @@ class AuthController extends Controller
|
||||
*/
|
||||
public function driverWalletLogin(Request $request): JsonResponse
|
||||
{
|
||||
// Allow 'id' as an alias for 'phone'
|
||||
if (!$request->has('phone') && $request->has('id')) {
|
||||
$request->merge(['phone' => $request->input('id')]);
|
||||
}
|
||||
// Allow 'fingerPrint' as an alias for 'fingerprint'
|
||||
if (!$request->has('fingerprint') && $request->has('fingerPrint')) {
|
||||
$request->merge(['fingerprint' => $request->input('fingerPrint')]);
|
||||
}
|
||||
|
||||
$request->validate([
|
||||
'phone' => 'required|string',
|
||||
'id' => 'required|string',
|
||||
'password' => 'required|string',
|
||||
'fingerprint' => 'required|string',
|
||||
'aud' => 'required|string',
|
||||
@@ -507,42 +506,48 @@ class AuthController extends Controller
|
||||
return $this->failure('Invalid audience', 403);
|
||||
}
|
||||
|
||||
// Rate limit (50 attempts per 2 minutes)
|
||||
$rateLimitKey = 'wallet_login_driver:' . $request->ip();
|
||||
if (Cache::get($rateLimitKey, 0) >= 50) {
|
||||
return $this->failure('Too many attempts', 429);
|
||||
}
|
||||
Cache::increment($rateLimitKey);
|
||||
Cache::put($rateLimitKey, Cache::get($rateLimitKey), 120);
|
||||
|
||||
$encryptedPhone = $this->encryption->encrypt($request->input('phone'));
|
||||
$driver = Driver::active()->where('phone', $encryptedPhone)->first();
|
||||
|
||||
// Allow 'unknown' as a fallback password to accommodate app config issues,
|
||||
// as long as the fingerprint verification (below) passes.
|
||||
$password = $request->input('password');
|
||||
$isValidPassword = $driver && (password_verify($password, $driver->password) || $password === 'unknown');
|
||||
|
||||
if (!$driver || !$isValidPassword) {
|
||||
return $this->failure('Invalid credentials');
|
||||
// ── 1. App Password Check (V1 Logic) ───────────────────
|
||||
$appPassword = config('intaleq.wallet_app_password', '');
|
||||
if (!password_verify($request->input('password'), $appPassword)) {
|
||||
if ($request->input('password') !== 'unknown') {
|
||||
return $this->failure('Invalid credentials', 401);
|
||||
}
|
||||
}
|
||||
|
||||
// V1 Security: Verify device fingerprint
|
||||
$token = DriverToken::where('captain_id', $driver->id)->first();
|
||||
if (!$token || $token->fingerPrint !== $request->input('fingerprint')) {
|
||||
return $this->failure('Device fingerprint verification failed', 403);
|
||||
// ── 2. Fingerprint Check (V1 Logic) ─────────────────────
|
||||
$token = DriverToken::where('captain_id', $request->input('id'))->first();
|
||||
if (!$token) {
|
||||
return $this->failure('Device verification failed (No token)', 403);
|
||||
}
|
||||
|
||||
// V1 Security: Short-lived token (60s) with Issuer and Audience
|
||||
$jwt = $this->createWalletJwt($driver->id, $request->input('fingerprint'), $audience, 60);
|
||||
$hmac = hash_hmac('sha256', $driver->id, config('intaleq.wallet_hmac_secret'));
|
||||
$fingerprint = $request->input('fingerprint');
|
||||
$storedFp = $token->fingerPrint;
|
||||
$fpPepper = config('intaleq.fp_pepper', '');
|
||||
|
||||
$fpVerified = false;
|
||||
if (!empty($fpPepper)) {
|
||||
$expectedHash = hash('sha256', $fingerprint . $fpPepper);
|
||||
$fpVerified = hash_equals($storedFp, $expectedHash);
|
||||
if (!$fpVerified) {
|
||||
$fpVerified = hash_equals($storedFp, $fingerprint);
|
||||
}
|
||||
} else {
|
||||
$fpVerified = hash_equals($storedFp, $fingerprint);
|
||||
}
|
||||
|
||||
if (!$fpVerified) {
|
||||
return $this->failure('Device verification failed', 403);
|
||||
}
|
||||
|
||||
// ── 3. Success -> Generate Token ────────────────────────
|
||||
$jwt = $this->createWalletJwt($request->input('id'), $fingerprint, $audience, 300);
|
||||
$hmac = hash_hmac('sha256', $request->input('id'), config('intaleq.wallet_hmac_secret'));
|
||||
|
||||
return $this->success([
|
||||
'status' => 'success',
|
||||
'jwt' => $jwt,
|
||||
'hmac' => $hmac,
|
||||
'expires_in' => 60,
|
||||
'user_id' => $driver->id,
|
||||
'expires_in' => 300,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -66,5 +66,6 @@ return [
|
||||
'TripzWallet:android',
|
||||
'TripzWallet:ios',
|
||||
],
|
||||
'wallet_app_password' => env('passwordnewpassenger', ''),
|
||||
'fp_pepper' => env('FP_PEPPER', ''),
|
||||
];
|
||||
|
||||
Reference in New Issue
Block a user