PatrickBauer's avatar

How to test if a user which tries to log in is confirmed yet

Hi guys, I know laravel doesn't provide an email confirmation machanism for new users but I'm trying to implement my own.

As soon as the user tries to log in, I'm dispatching an event handler for the auth.attemt event and do my confirmation check.

How do I link back to the login page and show the user an error message? Is the event system not the right choice for this kind of task?

I already tried thing like

Redirect::back()->withErrors(['test' => 'Error message'])->send();

or

Session::flash('errors', ['test' => 'Test']);
    Redirect::back()->send();

which both didn't work like I hoped they would.

0 likes
11 replies
pmall's avatar

As soon as the user tries to log in, I'm dispatching an event handler for the auth.attemt event and do my confirmation check.

This is to much, why not checking directly.

if(!$user->is_confirmed) return Redirect::back()->withErrors(['unconfirmed' => 'Unconfirmed']);

PatrickBauer's avatar

Would I do this by overriding the postLogin() function in the provided AuthController.php and adding this line?

graham's avatar

I've added an additional check in App\Http\Middleware\Authenticate.php

    public function handle($request, Closure $next)
    {
        if ($this->auth->guest())
        {
            if ($request->ajax())
            {
                return response('Unauthorized.', 401);
            }
            else
            {
                return redirect()->guest('login');
            }
        }
        if ( ! $this->auth->user()->isActivated() )
        {
            return redirect('/activate');
        }
        else
        {
            return $next($request);
        }
    }
graham's avatar

and this in

App\User.php

    public function isActivated()
    {
        Log::info('About to runn isActivated check');
        return (bool) $this->is_active ;
    }
PatrickBauer's avatar

I like the solution using the Auth middleware, because it allows the user to log in and still denies him sites he's not yet allowed to visit. Thanks :)

pmall's avatar

I really don't think it belongs to a middleware. Just redirect to the activate page if he is not activated, in the postLogin method if you want, that's all.

graham's avatar

@pmall, I think it depends what you're looking for.

I wanted something that would allow me to de-activate a user mid-session if necessary.

martinbean's avatar

@Graham @pmall I would instead create a new middleware class that only deals with checking if a user is activated. After all, that is exactly how middleware is supposed to be structured: you’re supposed to “stack” it, instead of just lumping everything into existing middleware classes.

1 like
graham's avatar

@PatrickBauer, @martinbean was absolutely right.

Here's my new version

App\Http\Kernel.php

    protected $routeMiddleware = [
        'auth' => 'App\Http\Middleware\Authenticate',
        'auth.basic' => 'Illuminate\Auth\Middleware\AuthenticateWithBasicAuth',
        'guest' => 'App\Http\Middleware\RedirectIfAuthenticated',
        'activated.email' => 'App\Http\Middleware\RedirectIfNotMailActivated',
    ];

App\Http\Middleware\RedirectIfNotMailActivated.php

<?php namespace App\Http\Middleware;
use Closure;
use Illuminate\Contracts\Auth\Guard;

class RedirectIfNotMailActivated {

    protected $auth;

    public function __construct(Guard $auth)
    {
        $this->auth = $auth;
    }

    public function handle($request, Closure $next)
    {
        if ( ! $this->auth->user()->isActivated() )
        {
            return redirect('/activate');
        }
        else
        {
            return $next($request);
        }
    }

}

Then add to the appropriate controller:

    public function __construct()
    {
        $this->middleware('auth');
        $this->middleware('activated.email');
        $this->middleware('activated.sms');
    }
willvincent's avatar

To @pmall's point, it may not necessarily belong in the default Authenticate middleware that ships with laravel, but middleware does seem like a good place for it, if email confirmation is a requirement for access.

Middleware is specifically for stuff like this, some scenario that affects whether or not user X has access to Y and whatnot.

@martinbean++

@Graham your new version looks good to me.

jekinney's avatar

Set it as global like the csrf middleware. Like that approach. Good to know.

Please or to participate in this conversation.