12

I use the included authentication of laravel 5.1.6 and want to know how I can extend it, to work like this:

if (Auth::attempt(['email' => $email, 'password' => $password, 'active' => 1])) {
    // The user is active, not suspended, and exists.
}

If the user is not "active", the login should not be possible. I have an 'active' column in the users table , with 0 or 1 as value. How can i do this while still using the built in authentication with login throtteling.

edit:

I don't have a postLogin function in the AuthController, only a use AuthenticatesAndRegistersUsers, ThrottlesLogins; , a __construct(), a validator() and a create() function. Do I have to change something in the trait in Illuminate\Foundation\Auth\.. or must I add the the postLogin() function in the AuthController ?

haheute
  • 2,129
  • 3
  • 32
  • 49
  • 2
    possible duplicate of [Login only if user is active using Laravel](http://stackoverflow.com/questions/31015606/login-only-if-user-is-active-using-laravel) – BrokenBinary Jul 06 '15 at 11:40
  • 1
    `postLogin` function is defined in `AuthenticatesAndRegistersUsers` trait but you can override it by copying it in `AuthController` and then you can modify it. – pinkal vansia Jul 06 '15 at 11:53
  • 1
    AuthController uses the `postLogin` function from `AuthenticatesAndRegistersUsers`. You need to overwrite that one by placing a new `postLogin` function in your AuthController. Look at the question I linked in my previous comment. – BrokenBinary Jul 06 '15 at 11:53

5 Answers5

21

You can just override the getCredentials() method in your AuthController:

class AuthController extends Controller
{
    use AuthenticatesAndRegistersUsers;

    public function getCredentials($request)
    {
        $credentials = $request->only($this->loginUsername(), 'password');

        return array_add($credentials, 'active', '1');
    }
}

This will add the active = 1 constraint when trying to authenticate a user.

EDIT: If you want a separate error message like BrokenBinary says, then Laravel allows you to define a method called authenticated that is called after a user has been authenticated, but before the redirect, allowing you to do any post-login processing. So you could utilise this by checking if the authenticated user is active, and throw an exception or display an error message if not:

class AuthController extends Controller
{
    use AuthenticatesAndRegistersUsers;

    public function authenticated(Request $request, User $user)
    {
        if ($user->active) {
            return redirect()->intended($this->redirectPath());
        } else {
            // Raise exception, or redirect with error saying account is not active
        }
    }
}

Don’t forget to import the Request class and User model class.

Community
  • 1
  • 1
Martin Bean
  • 38,379
  • 25
  • 128
  • 201
  • 2
    If an inactive user tries to login they will receive the same "Invalid credentials" error message as they would for a non-matching email/password. You should really tell the user they failed to login because their account was inactive. – BrokenBinary Jul 06 '15 at 12:39
  • 1
    i have this `authenticated` method..but its not being called..any help? – slier Mar 09 '16 at 09:58
  • 1
    when using the authenticated method, keep in mind the user is actually already authenticated at this point. So you would have to manually log him out if he doesn't match your $user->active check. (before redirecting or throwing an exception) – Jones03 Sep 06 '16 at 10:45
9

I have now changed the auth middleware /app/Http/Middleware/Authenticate.php (added the block below the comment):

/**
 * Handle an incoming request.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Closure  $next
 * @return mixed
 */
public function handle($request, Closure $next)
{
    if ($this->auth->guest())
    {
        if ($request->ajax())
        {
            return response('Unauthorized.', 401);
        }
        else
        {
            return redirect()->guest('auth/login');
        }
    }

    #logout if user not active
    if($this->auth->check() && $this->auth->user()->active !== 1){
        $this->auth->logout();
        return redirect('auth/login')->withErrors('sorry, this user account is deactivated');
    }

    return $next($request);
}

It seems, it also logs out inactive users if they were already logged in.

haheute
  • 2,129
  • 3
  • 32
  • 49
2

I would add following first thing in postLogin() function.

       $this->validate($request, [
            'email' => 'required|email', 'password' => 'required',
        ]);

        if ($this->auth->validate(['email' => $request->email, 'password' => $request->password, 'active' => 0])) {
            return redirect($this->loginPath())
                ->withInput($request->only('email', 'remember'))
                ->withErrors('Your account is Inactive or not verified');
        }

active is a flag in user table. 0 = Inactive, 1 = active. so whole function would look like following..

public function postLogin(Request $request)
    {
        $this->validate($request, [
            'email' => 'required|email', 'password' => 'required',
        ]);
        if ($this->auth->validate(['email' => $request->email, 'password' => $request->password, 'active' => 0])) {
            return redirect($this->loginPath())
                ->withInput($request->only('email', 'remember'))
                ->withErrors('Your account is Inactive or not verified');
        }
        $credentials  = array('email' => $request->email, 'password' => $request->password);
        if ($this->auth->attempt($credentials, $request->has('remember'))){
                return redirect()->intended($this->redirectPath());
        }
        return redirect($this->loginPath())
            ->withInput($request->only('email', 'remember'))
            ->withErrors([
                'email' => 'Incorrect email address or password',
            ]);
    }
pinkal vansia
  • 10,240
  • 5
  • 49
  • 62
  • Your first validation check will return "Your account is Inactive or not verified" for a bad email/password too. You should validate email/password, then validate active, then login if those didn't fail. – BrokenBinary Jul 06 '15 at 11:39
  • You could look at my answer on another question. http://stackoverflow.com/questions/31015606/login-only-if-user-is-active-using-laravel/31016210#31016210 – BrokenBinary Jul 06 '15 at 11:39
  • '$this->validate' validates if both valid email and password supplied. – pinkal vansia Jul 06 '15 at 11:40
  • I'm talking about your first `if()` statement. If the user is active but provides non-matching email/pasword, then it still returns the "Your account is Inactive or not verified" error message. – BrokenBinary Jul 06 '15 at 11:43
  • If you see, if user provides valid email and password and if 'active' =0 (inactive) then only if condition stands true. otherwise it will attempt to login with supplied email,password – pinkal vansia Jul 06 '15 at 11:47
  • Ok, I see what you're saying. This works, but it's a strange way of doing it. – BrokenBinary Jul 06 '15 at 11:55
  • I will have to add to the conversation, the problem here is that people don't see that first `if()` is `auth->validate` instead of second `if()` which is `auth->attempt`. I had a same problem realizing this, and even laravel documentations don't cover it. In my version it's `Auth::validate` and after reading that it's `Auth::validate` i came here to upvote this because it's best and clean solution. – lonerunner Aug 16 '15 at 20:24
2

Solved: this link ( tutorial) will help you : https://medium.com/@mshanak/solved-tutorial-laravel-5-3-disable-enable-block-user-login-web-passport-oauth-4bfb74b0c810

step1:

add new field to the User table called ‘status’ (1:enabled, 0:disabed)

step2:

to block the web login , in app/Http/Controllers/Auth/LoginController.php add the follwoing function:

/**
 * Get the needed authorization credentials from the request.
 *
 * @param \Illuminate\Http\Request $request
 * @return array
 */
 protected function credentials(\Illuminate\Http\Request $request)
 {
 $credentials = $request->only($this->username(), ‘password’);

return array_add($credentials, ‘status’, ‘1’);
 }

Step3:

to block the user when using passport authentication ( token ) , in the User.php model add the following function :

public function findForPassport($identifier) {
     return User::orWhere(‘email’, $identifier)->where(‘status’, 1)->first();
     }

Done :)

Mahdi
  • 835
  • 8
  • 6
1

On Laravel 5.3.* update app/Http/Controllers/Auth/LoginController

class LoginController extends Controller
{

    use AuthenticatesUsers;

    /**
     * Get the needed authorization credentials from the request.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return array
     */
    protected function credentials(\Illuminate\Http\Request $request)
    {
        $credentials = $request->only($this->username(), 'password');

        return array_add($credentials, 'active', '1');
    }

    // your code here
borracciaBlu
  • 4,017
  • 3
  • 33
  • 41