I am new to Laravel but fell in love with the framework and decided to use it for my project.
I have a field active
and by default I've set it to 0
. In the Attempt()
method, I've set $credentials['active'] = 1
. When I logout and login again, this works fine.
But when I register a user, it automatically logs the user in without checking active field.
I assume you are using the AuthenticatesAndRegistersUsers
trait in your controller.
The registration is carried by the postRegister()
method in that trait, which calls the login()
method after creating a new user.
You can override this method in your controller and call the login()
method only when the active
field is true
. So, your postRegister()
method will be something like:
public function postRegister(Request $request)
{
$validator = $this->registrar->validator($request->all());
if ($validator->fails())
{
$this->throwValidationException(
$request, $validator
);
}
$user = $this->registrar->create($request->all());
if ($request->get('active')) {
$this->auth->login($user);
}
return redirect($this->redirectPath());
}
In registersUsers.php replace the line:
Auth::guard($this->getGuard())->login($this->create($request->all()));
With the following:
$this->create($request->all());
This worked for me, I use Laravel 5.2
I would avoid adding the active
field to the credentials - this is an authorisation issue rather than an authentication one.
For this, I'd use a middleware to check if a logged-in user is active or inactive.
In 5.3, the middleware would look like this:
<?php
namespace App\Http\Middleware;
use Closure;
use Illuminate\Support\Facades\Auth;
class RedirectIfInactive
{
/**
* Handle an incoming request.
*
* @param \Illuminate\Http\Request $request
* @param \Closure $next
* @return mixed
*/
public function handle($request, Closure $next)
{
if ( $user = Auth::guard('web')->user() ) {
if ( ! $user->active )
return redirect(route('account_inactive'));
}
return $next($request);
}
}
This middleware then has to be registered inside Kernel.php
:
protected $routeMiddleware = [
'auth' => \Illuminate\Auth\Middleware\Authenticate::class,
'auth.basic' => \Illuminate\Auth\Middleware\AuthenticateWithBasicAuth::class,
'bindings' => \Illuminate\Routing\Middleware\SubstituteBindings::class,
'can' => \Illuminate\Auth\Middleware\Authorize::class,
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
'inactive' => \App\Http\Middleware\RedirectIfInactive::class,
];
And then finally we protect all our routes with it:
Route::get('inactive', ['as' => 'account_inactive', function () {
return view('inactive');
}]);
Route::group(['prefix' => 'admin', 'namespace' => 'Admin', 'middleware' => 'inactive'], function () {
Route::get('/', ['as' => 'admin.home', 'uses' => 'AdminController@index']);
});
The advantage of this approach of course is that we can display a more relevant error message than the general 'These credentials do not match our records' that people with bad auth details get. So the user would know it's not their fault they can't log in.
Anyway, with the approach in the accepted answer, ensure you have done the same for when the user successfully resets their password as they are also auto-logged in then.