laravel / framework

The Laravel Framework.
https://laravel.com
MIT License
32.39k stars 10.98k forks source link

[5.2] Auth scaffolding 'Reset Password' ignores provider config setting and tries to find email in default users table when using multi-auth. #13169

Closed AndrewFeeney closed 8 years ago

AndrewFeeney commented 8 years ago

I've set up multi-auth in two separate applications now and in both I noticed this issue. For example, in one application there are two separate user tables 'users' and 'admins' which both use the Eloquent auth driver. I copied the out of the box Auth controllers to make Admin/AuthController and Admin/PasswordController and authentication works as expected for both tables. However, for the admin users when requesting a password reset email, the form validation fails with "We can't find a user with that e-mail address." for any users in the admins table but works for users in the users table. Here is the config/auth.php file:

/*
|--------------------------------------------------------------------------
| Authentication Defaults
|--------------------------------------------------------------------------
|
| This option controls the default authentication "guard" and password
| reset options for your application. You may change these defaults
| as required, but they're a perfect start for most applications.
|
*/

'defaults' => [
    'guard' => 'web',
    'passwords' => 'users',
],

/*
|--------------------------------------------------------------------------
| Authentication Guards
|--------------------------------------------------------------------------
|
| Next, you may define every authentication guard for your application.
| Of course, a great default configuration has been defined for you
| here which uses session storage and the Eloquent user provider.
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| Supported: "session", "token"
|
*/

'guards' => [
    'web' => [
        'driver' => 'session',
        'provider' => 'users',
    ],

    'admin' => [
        'driver' => 'session',
        'provider' => 'admins'
    ],
],

/*
|--------------------------------------------------------------------------
| User Providers
|--------------------------------------------------------------------------
|
| All authentication drivers have a user provider. This defines how the
| users are actually retrieved out of your database or other storage
| mechanisms used by this application to persist your user's data.
|
| If you have multiple user tables or models you may configure multiple
| sources which represent each model / table. These sources may then
| be assigned to any extra authentication guards you have defined.
|
| Supported: "database", "eloquent"
|
*/

'providers' => [
    'users' => [
        'driver' => 'eloquent',
        'model' => App\User\User::class,
    ],
    'admins' => [
        'driver' => 'eloquent',
        'model' => App\User\Admin::class,
    ],
],

/*
|--------------------------------------------------------------------------
| Resetting Passwords
|--------------------------------------------------------------------------
|
| Here you may set the options for resetting passwords including the view
| that is your password reset e-mail. You may also set the name of the
| table that maintains all of the reset tokens for your application.
|
| You may specify multiple password reset configurations if you have more
| than one user table or model in the application and you want to have
| separate password reset settings based on the specific user types.
|
| The expire time is the number of minutes that the reset token should be
| considered valid. This security feature keeps tokens short-lived so
| they have less time to be guessed. You may change this as needed.
|
*/

'passwords' => [
    'users' => [
        'provider' => 'users',
        'email' => 'auth.emails.password',
        'table' => 'password_resets',
        'expire' => 60,
    ],
    'admins' => [
        'provider' => 'admins',
        'email' => 'auth.emails.password',
        'table' => 'password_resets',
        'expire' => 60,
    ]
]

The only solution I was able to find for this problem was the one suggested by @shekercasanova on the Laracasts forum here: https://laracasts.com/discuss/channels/laravel/password-reset-for-multiple-tables?page=1 where the default passwords value is overridden with Config::set(). Shouldn't the Reset Password function be using the 'passwords' array in the config/auth.php file to determine the provider and thereby the table to search for when validating the form submission? I tried to dig into the source to locate the source of the issue. I got as far as working out that Illuminate\Auth\EloquentUserProvider's retrieveByCredentials() method looks at it's $model property to get the user model and hence the table to look up the user. I'm not sure where this class is instantiated and the model property is set so I couldn't quite get to the bottom of what you might change to fix it, if it is a bug. Apologies if I've just misconfigured something.

guillemc commented 8 years ago

I had the same issue. You should specify the correct password broker to use in Admin\PasswordContoller:

 protected $broker = 'admins';