Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Redirect if authenticated logic in Laravel's built-in auth?

This question has been asked before, and I believe my code to be correct, but I am getting strange behaviour.

I need to redirect the user to different routes after login depending on some database values. I thought that in order to do this I simply had to place my logic in the handle method of app/Http/Middleware/RedirectIfAuthenticated.php. My method currently looks like so:

public function handle($request, Closure $next)
{

    if ($this->auth->check()) {
        if($this->auth->user()->sign_up_complete == 1){
            return redirect('/');
        } else {
            if($this->auth->user()->step_one_complete == 0){
                return redirect('/register/step-1');
            } elseif($this->auth->user()->step_two_complete == 0){
                return redirect('/register/step-2');
            } else {
                return redirect('/');
            }
        }
    }

    return $next($request);
}

This does not work, and upon login the user is redirected to /home. I have tried placing dd($this->auth->user()) inside the $this->auth->check() condition, but it never gets run. If I place it outside of that check then it's run on every request. It looks like $this->auth->check() is never run.

My question: If not here, where should this logic go?

I have removed protected $redirectTo = '/account'; from the AuthController.php controller too.

like image 383
Mike Avatar asked Oct 26 '15 08:10

Mike


3 Answers

To understand why your routing logic is never reached, you should look in app/Http/Kernel.php where the RedirectIfAuthenticated middleware is registered:

protected $routeMiddleware = [
    ...
    'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
    ...
];

This means if a user navigates to a route that is not protected by the guest route middleware, the request never passes through the RedirectIfAuthenticated class and so misses your logic completely.

You can add guest middleware to your registration routes in your routes file to force the routing to pass through your code like this:

Route::get('/register/step-1', '<YOUR CONTROLLER METHOD>')->middleware('guest');

But, since you say the user is already logged in (not a guest) you should instead move your code as suggested by the other answers.

Only adding this as an answer, because it couldn't be clarified in the space allowed by a comment.

like image 184
Jannie Theunissen Avatar answered Nov 09 '22 20:11

Jannie Theunissen


High level answer: the purpose of RedirectIfAuthenticated is to keep an already authenticated user from reaching the login or registration routes/views since they're already logged in.

Test: bookmark the login view. Then login. Close the browser or window. Open the login bookmark. You'll go straight to user's home or where ever specified in RedirectIfAuthenticated.

For purposes of the LoginController, create a redirecTo() method, which is what the redirectPath() method looks for to see if you have customized the redirect.

// example
public function redirectTo()
{
    switch (auth()->user()->role) {
        case 'foo':
            return route('foo.home');

        case 'bar':
            return route('bar.home');

        default:
            auth()->logout();
            return route('web.welcome');
    }
}
like image 41
mangonights Avatar answered Nov 09 '22 18:11

mangonights


You are not using the middleware correctly. This piece of code will fire everytime you send a request when you are logged in.

To change the redirect location after login you can override the redirectPath() method in your AuthController. (You can find the original method in vendor/laravel/framework/src/Illuminate/Foundation/Auth/RedirectsUsers.php)

This would look something like this:

...

public class AuthController extends Controller {

    ...

    public function redirectPath()
    {
        if(Auth::user()->sign_up_complete == 1) {
            return '/';
        } else {
            if(Auth::user()->step_one_complete == 0) {
                return '/register/step-1';
            } elseif(Auth::user()->step_two_complete == 0) {
                return '/register/step-2';
            } else {
                return '/';
            }
        }
    }


    // The rest of the class implementation.

}

Note: I've replaced the $this->auth() method with the Facade alternative (Auth::). Just because I am not sure if the AuthController has an auth() method.

like image 8
Mark Walet Avatar answered Nov 09 '22 18:11

Mark Walet