The following Guide is optimized for Laravel 7, but it works for Laravel 6.x and Laravel 5.x, too. Differences should only be present in the paths.
A great way to start a simple web project with PHP which needs a login and / or registration form with permissions is by using the widespread Laravel Framework with the Laratrust Package. This yields to a quick set up working system with basic functionalities.
TL;DR
Check out the short version of my StackOverflow answer.
Customize Login Validation
If the project grows, there might be a time where you want to customize the authentication mechanism by defining your own login validation: Perhaps you want to create a new status
field for users to forbid the login for specific values or you want to add a lifetime (date
field) for accounts that will lead to a failed login when the date-value is in the past. Anyway, you have to extend the existing login validation process.
This validation process is made in the validateCredentials
method in the EloquentUserProvider
class, located at [PROJECTROOT]/vendor/laravel/framework/src/Illuminate/Auth/EloquentUserProvider.php
which looks as follows in Laravel 7:
/**
* Validate a user against the given credentials.
*
* @param \Illuminate\Contracts\Auth\Authenticatable $user
* @param array $credentials
* @return bool
*/
public function validateCredentials(UserContract $user, array $credentials)
{
$plain = $credentials['password'];
return $this->hasher->check($plain, $user->getAuthPassword());
}
Default validateCredentials
method in EloquentUserProvider
This method must be extended to get things working. As a good and attentive developer, you know that the framework default methods should never be touched to be more stable for future updates and avoid side effects. As a result and a possible solution, a Custom Provider can be defined to override the existing function.
Define Custom Provider and override validateCredentials
First, create a new file called CustomUserProvider.php
(or a better name, for example AuthValidateStatusServiceProvider.php
if you want to check the user status before login) in the app/Providers
directory with the following code:
<?php
namespace App\Providers;
use Illuminate\Auth\EloquentUserProvider as UserProvider;
use Illuminate\Contracts\Auth\Authenticatable as UserContract;
class CustomUserProvider extends UserProvider {
/**
* Overrides the framework defaults validate credentials method
*
* @param UserContract $user
* @param array $credentials
* @return bool
*/
public function validateCredentials(UserContract $user, array $credentials) {
$plain = $credentials['password'];
// PUT YOUR CUSTOM VALIDATION HERE
return $this->hasher->check($plain, $user->getAuthPassword());
}
}
Custom Provider
Add your custom validation and save it, for example if ($user->status != 'active') return false;
if you created a status
attribute for the user.
After this, Laravel must call this provider at the correct execution step. Do this by extending the boot()
method in the app/Providers/AuthServiceProvider.php
file to register it:
/**
* Register any authentication / authorization services.
*
* @return void
*/
public function boot()
{
$this->registerPolicies();
\Illuminate\Support\Facades\Auth::provider('customuserprovider', function($app, array $config) {
return new CustomUserProvider($app['hash'], $config['model']);
});
}
boot()
method in the AuthServiceProvider
Remember to change the provider class name on both points. Furthermore, the code can be shortened with a simple import statement.
We are not done yet! The last step will be in the config/auth.php
file. Scroll to the User Providers part and change it to:
'providers' => [
'users' => [
'driver' => 'customuserprovider',
'model' => App\User::class,
'table' => 'users',
],
],
User Providers part in auth.php
Here again: Don't forget to change the driver name (provider class name)
That's it! Now, your custom login validation should automatically be called after the user hits the Login button.