Page MenuHomePhorge

D5090.1775289752.diff
No OneTemporary

Authored By
Unknown
Size
4 KB
Referenced Files
None
Subscribers
None

D5090.1775289752.diff

diff --git a/src/app/User.php b/src/app/User.php
--- a/src/app/User.php
+++ b/src/app/User.php
@@ -15,6 +15,7 @@
use Dyrynda\Database\Support\NullableFields;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Notifications\Notifiable;
+use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Hash;
use Illuminate\Foundation\Auth\User as Authenticatable;
@@ -782,10 +783,11 @@
* @param string $username The username
* @param string $password The password in plain text
* @param ?string $clientIP The IP address of the client
+ * @param ?bool $withChecks Enable MFA and location checks
*
* @return array ['user', 'reason', 'errorMessage']
*/
- public static function findAndAuthenticate($username, $password, $clientIP = null, $verifyMFA = true): array
+ public static function findAndAuthenticate($username, $password, $clientIP = null, $withChecks = true): array
{
$error = null;
@@ -800,18 +802,28 @@
} else {
if ($userid = AuthUtils::tokenValidate($password)) {
if ($user->id == $userid) {
- $verifyMFA = false;
+ $withChecks = false;
} else {
$error = AuthAttempt::REASON_PASSWORD;
}
} else {
+ if (!$withChecks) {
+ $cacheId = hash('sha256', "{$user->id}-$password");
+ // Skip the slow password verification for cases where we also don't verify mfa.
+ // We rely on this for fast cyrus-sasl authentication.
+ if (Cache::has($cacheId)) {
+ \Log::debug("Cached authentication for {$user->email}");
+ return ['user' => $user];
+ }
+ }
+
if (!$user->validatePassword($password)) {
$error = AuthAttempt::REASON_PASSWORD;
}
}
}
- if ($verifyMFA) {
+ if ($withChecks) {
// Check user (request) location
if (!$error && !$user->validateLocation($clientIP)) {
$error = AuthAttempt::REASON_GEOLOCATION;
@@ -855,6 +867,11 @@
\Log::info("Successful authentication for {$user->email}");
+ if (!empty($cacheId)) {
+ // Cache for 60s
+ Cache::put($cacheId, true, 60);
+ }
+
return ['user' => $user];
}
diff --git a/src/tests/Feature/UserTest.php b/src/tests/Feature/UserTest.php
--- a/src/tests/Feature/UserTest.php
+++ b/src/tests/Feature/UserTest.php
@@ -11,6 +11,7 @@
use App\User;
use App\Auth\Utils as AuthUtils;
use Carbon\Carbon;
+use Illuminate\Support\Benchmark;
use Illuminate\Support\Facades\Queue;
use Tests\TestCase;
@@ -1638,4 +1639,44 @@
$token = AuthUtils::tokenCreate($this->getTestUser('ned@kolab.org')->id);
$this->assertFalse(isset(User::findAndAuthenticate($user->email, $token)['user']));
}
+
+ /**
+ * Test User password validation
+ */
+ public function testBenchmarkFindAndAuthenticatePassword(): void
+ {
+ Queue::fake();
+
+ $user = $this->getTestUser('user-test@' . \config('app.domain'), ['password' => 'test']);
+
+ // Seed the cache
+ User::findAndAuthenticate($user->email, "test");
+ $time = Benchmark::measure(function() use (&$user) {
+ User::findAndAuthenticate($user->email, "test");
+ }, 10);
+ // print("\nTime: $time ms\n");
+ // We want this to be faster than the slow default bcrypt algorithm
+ $this->assertTrue($time < 10);
+ }
+
+ /**
+ * Test User token validation
+ */
+ public function testBenchmarkFindAndAuthenticateToken(): void
+ {
+ Queue::fake();
+
+ $user = $this->getTestUser('user-test@' . \config('app.domain'), ['password' => 'test']);
+ $token = AuthUtils::tokenCreate($user->id);
+
+ // Seed the cache
+ User::findAndAuthenticate($user->email, $token);
+ $time = Benchmark::measure(function() use ($user, $token) {
+ User::findAndAuthenticate($user->email, $token);
+ }, 10);
+ // print("\nTime: $time ms\n");
+ // We want this to be faster than the slow default bcrypt algorithm
+ $this->assertTrue($time < 10);
+ }
+
}

File Metadata

Mime Type
text/plain
Expires
Sat, Apr 4, 8:02 AM (11 h, 30 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
18828605
Default Alt Text
D5090.1775289752.diff (4 KB)

Event Timeline