fix: Isolate OTP keys and sessions per role in Redis so teacher and student logins on the same phone number never collide
This commit is contained in:
@@ -77,11 +77,13 @@ class AuthController
|
||||
// 2. Generate 6-digit OTP
|
||||
$otp = (string)random_int(100000, 999999);
|
||||
|
||||
// 3. Save OTP in Redis (TTL: 300s / 5 minutes)
|
||||
// 3. Save OTP in Redis (TTL: 300s / 5 minutes) - Role-isolated to prevent Teacher/Student collision
|
||||
try {
|
||||
$redis = RedisClient::getInstance();
|
||||
$otpKey = "otp:{$phoneHash}";
|
||||
$otpKey = "otp:{$phoneHash}:{$role}";
|
||||
$redis->setex($otpKey, 300, password_hash($otp, PASSWORD_BCRYPT));
|
||||
// Also store general key for backwards compatibility
|
||||
$redis->setex("otp:{$phoneHash}", 300, password_hash($otp, PASSWORD_BCRYPT));
|
||||
} catch (\Exception $e) {
|
||||
error_log("Redis OTP store error: " . $e->getMessage());
|
||||
}
|
||||
@@ -162,14 +164,16 @@ class AuthController
|
||||
|
||||
$phoneHash = Security::blindIndex($cleanPhone);
|
||||
|
||||
// 1. Verify OTP against Redis
|
||||
// 1. Verify OTP against Redis (Check role-isolated key first, then fallback)
|
||||
$redis = RedisClient::getInstance();
|
||||
$otpRoleKey = "otp:{$phoneHash}:{$role}";
|
||||
$otpKey = "otp:{$phoneHash}";
|
||||
$storedHash = $redis->get($otpKey);
|
||||
$storedHash = $redis->get($otpRoleKey) ?: $redis->get($otpKey);
|
||||
|
||||
$isValidOtp = false;
|
||||
if ($storedHash && password_verify($inputOtp, $storedHash)) {
|
||||
$isValidOtp = true;
|
||||
$redis->del($otpRoleKey);
|
||||
$redis->del($otpKey); // Invalidate OTP after success
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user