Inconsistent Behavior in EloquentUserProvider::retrieveByCredentials on Missing User - Clarification #56038
Replies: 6 comments
-
No. A generic user instance is only returned when the data record is not framework/src/Illuminate/Auth/DatabaseUserProvider.php Lines 141 to 146 in 11e3363 |
Beta Was this translation helpful? Give feedback.
-
<?php
use Illuminate\Auth\DatabaseUserProvider;
use Illuminate\Support\Facades\Artisan;
Artisan::command('local:user {email}', function (string $email) {
$userProvider = app(DatabaseUserProvider::class, ['table' => 'users']);
dump($userProvider->retrieveByCredentials(['email' => $email]));
});
For shipped user on $ php artisan local:user [email protected]
Illuminate\Auth\GenericUser^ {#536
#attributes: array:8 [
"id" => 1
"name" => "Test User"
"email" => "[email protected]"
"email_verified_at" => "2025-06-13 14:33:24"
"password" => "$2y$12$jan2XHAmy0NOioevaKmmg.98rdf/GRN7AI2GnwBpDfqosBVyBfBcG"
"remember_token" => "m4kTnrJ7MG"
"created_at" => "2025-06-13 14:33:24"
"updated_at" => "2025-06-13 14:33:24"
]
} // routes/console.php:9 For a non-existent user: $ php artisan local:user [email protected]
null // routes/console.php:9 |
Beta Was this translation helpful? Give feedback.
-
You're right, my apologies, i was deceived by the code format. The reason we initially raised this is that we’re using a custom guard (JWTGuard based on php-open-source-saver/jwt-auth), and we noticed that in some flows the validateCredentials() method isn’t called when the user is not found. This led us to investigate timing differences during login attempts, raising concerns about potential username enumeration via timing attacks. |
Beta Was this translation helpful? Give feedback.
-
You can customize the timebox time span by adding this config key to your project's return [
// ... other configuration
'timebox_duration' => 200000, // time in microseconds (e.g. milliseconds * 1000)
]; Then you can change it to whatever value fits your use-case better. Reference: framework/src/Illuminate/Auth/AuthManager.php Lines 124 to 130 in 11e3363 |
Beta Was this translation helpful? Give feedback.
-
In most cases, you can’t know in advance which value is best, so changing it wouldn't necessarily be beneficial. It depends on how loaded the database is, the infrastructure, or other factors. The definitive fix would be to check the password hash even if the user doesn’t exist, this would allow to have similar response times both when the user exists but the password is wrong, and when the user doesn’t exist. |
Beta Was this translation helpful? Give feedback.
-
Well, in that case, you are better off proposing a PR to change that behavior. But I guess the issue reported originally can be closed, right? Also, I just noticed you are using Laravel 10, which is EOL. https://laravel.com/docs/12.x/releases#support-policy You can convert this issue into a discussion in case you want to gather feedback for any intended change. |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
-
Laravel Version
10.48.29
PHP Version
8.2.26
Database Driver & Version
No response
Description
While investigating an authentication-related issue, we came across a behavioral difference between EloquentUserProvider and DatabaseUserProvider.
When attempting an authentication using a guard with EloquentUserProvider, if the user is not found,
retrieveByCredentials()
returnsnull
, andvalidateCredentials()
is never called: https://github.com/laravel/framework/blob/12.x/src/Illuminate/Auth/SessionGuard.php#L481In contrast, DatabaseUserProvider returns a dummy user object even when no user is found, which causes validateCredentials() to be executed regardless.
We’re not sure if this is an intentional design decision or an inconsistency between the two providers, so we wanted to raise it here for clarification.
Thanks!
Steps To Reproduce
Just a clarification request, but it can be reproduced by checking the different retrieveByCredentials() method results using the two mentioned providers.
Beta Was this translation helpful? Give feedback.
All reactions