Laravel redirect back to original destination after login

LaravelRedirectLaravel 4

Laravel Problem Overview


This seems like a pretty basic flow, and Laravel has so many nice solutions for basic things, I feel like I'm missing something.

A user clicks a link that requires authentication. Laravel's auth filter kicks in and routes them to a login page. User logs in, then goes to the original page they were trying to get to before the 'auth' filter kicked in.

Is there a good way to know what page they were trying to get to originally? Since Laravel is the one intercepting the request, I didn't know if it keeps track somewhere for easy routing after the user logs in.

If not, I'd be curious to hear how some of you have implemented this manually.

Laravel Solutions


Solution 1 - Laravel

For Laravel 5.3 and above

Check Scott's answer below.

For Laravel 5 up to 5.2

Simply put,

On auth middleware:

// redirect the user to "/login"
// and stores the url being accessed on session
if (Auth::guest()) {
    return redirect()->guest('login');
}
return $next($request);

On login action:

// redirect the user back to the intended page
// or defaultpage if there isn't one
if (Auth::attempt(['email' => $email, 'password' => $password])) {
    return redirect()->intended('defaultpage');
}

For Laravel 4 (old answer)

At the time of this answer there was no official support from the framework itself. Nowadays you can use the method pointed out by bgdrl below this method: (I've tried updating his answer, but it seems he won't accept)

On auth filter:

// redirect the user to "/login"
// and stores the url being accessed on session
Route::filter('auth', function() {
    if (Auth::guest()) {
        return Redirect::guest('login');
    }
});

On login action:

// redirect the user back to the intended page
// or defaultpage if there isn't one
if (Auth::attempt(['email' => $email, 'password' => $password])) {
    return Redirect::intended('defaultpage');
}

For Laravel 3 (even older answer)

You could implement it like this:

Route::filter('auth', function() {
	// If there's no user authenticated session
	if (Auth::guest()) {
		// Stores current url on session and redirect to login page
		Session::put('redirect', URL::full());
		return Redirect::to('/login');
	}
	if ($redirect = Session::get('redirect')) {
		Session::forget('redirect');
		return Redirect::to($redirect);
	}
});

// on controller
public function get_login()
{
	$this->layout->nest('content', 'auth.login'); 
}

public function post_login()
{
	$credentials = [
		'username' => Input::get('email'),
		'password' => Input::get('password')
	];

	if (Auth::attempt($credentials)) {
		return Redirect::to('logged_in_homepage_here');
	}

	return Redirect::to('login')->with_input();
}

Storing the redirection on Session has the benefit of persisting it even if the user miss typed his credentials or he doesn't have an account and has to signup.

This also allows for anything else besides Auth to set a redirect on session and it will work magically.

Solution 2 - Laravel

Laravel >= 5.3

The Auth changes in 5.3 make implementation of this a little easier, and slightly different than 5.2 since the Auth Middleware has been moved to the service container.

Modify the new Middleware auth redirector
/app/Http/Middleware/RedirectIfAuthenticated.php

Change the handle function slightly, so it looks like:

public function handle($request, Closure $next, $guard = null)
{
    if (Auth::guard($guard)->check()) {
        return redirect()->intended('/home');
    }

    return $next($request);
}
TL;DR explanation

The only difference is in the 4th line; by default it looks like this:

return redirect("/home");

Since Laravel >= 5.3 automatically saves the last "intended" route when checking the Auth Guard, it changes to:

return redirect()->intended('/home');

That tells Laravel to redirect to the last intended page before login, otherwise go to "/home" or wherever you'd like to send them by default.

Hope this helps someone else - there's not much out there on the differences between 5.2 and 5.3, and in this area in particular there are quite a few.

Solution 3 - Laravel

I found those two great methods that might be extremely helpful to you.

Redirect::guest();
Redirect::intended();

You can apply this filter to the routes that need authentication.

Route::filter('auth', function()
{
	if (Auth::guest()) {
           return Redirect::guest('login');
    }
});

What this method basically does it's to store the page you were trying to visit and it is redirects you to the login page.

When the user is authenticated you can call

return Redirect::intended();

and it's redirects you to the page you were trying to reach at first.

It's a great way to do it although I usually use the below method.

Redirect::back()

You can check this awesome blog.

Solution 4 - Laravel

You may use Redirect::intended function. It will redirect the user to the URL they were trying to access before being caught by the authenticaton filter. A fallback URI may be given to this method in case the intended destinaton is not available.

In post login/register:

return Redirect::intended('defaultpageafterlogin');

Solution 5 - Laravel

Change your LoginControllers constructor to:

public function __construct()
    {
        session(['url.intended' => url()->previous()]);
        $this->redirectTo = session()->get('url.intended');
        
        $this->middleware('guest')->except('logout');
    }

It will redirect you back to the page BEFORE the login page (2 pages back).

Solution 6 - Laravel

I have been using this for a while on my language selector code. As long as you only need to go back by just 1 page it works fine:

return Redirect::to(URL::previous());

It ain't the most powerful solution out there but it is super-easy and can help solve a few puzzles. :)

Solution 7 - Laravel

return Redirect::intended('/');

this will redirect you to default page of your project i.e. start page.

Solution 8 - Laravel

For laravel 5.* try these.

return redirect()->intended('/');

or

return Redirect::intended('/');

Solution 9 - Laravel

For Laravel 8

Following approach works for me for Laravel 8.

Controller based approach

/app/Http/Controllers/Auth/AuthenticatedSessionController.php
Pre-login

The intended url will be stored in the session at create :

/**
 * Display the login view.
 *
 * @return \Illuminate\View\View
 */
public function create()
{
    session(['url.intended' => url()->previous()]);
    return view('auth.login');
}
Post-login

Upon successful login, in case a intended url is available in session then redirect to it otherwise redirect to the default one :

/**
 * Handle an incoming authentication request.
 *
 * @param  \App\Http\Requests\Auth\LoginRequest  $request
 * @return \Illuminate\Http\RedirectResponse
 */
public function store(LoginRequest $request)
{
    $request->authenticate();

    //in case intended url is available
    if (session()->has('url.intended')) {
        $redirectTo = session()->get('url.intended');
        session()->forget('url.intended');
    }

    $request->session()->regenerate();

    if ($redirectTo) {
        return redirect($redirectTo);
    }
    return redirect(RouteServiceProvider::HOME);
}

Solution 10 - Laravel

Laravel 3

I tweaked your (Vinícius Fragoso Pinheiro) code slightly, and placed the following in filters.php

Route::filter('auth', function()
{
    // If there's no user authenticated session
    if (Auth::guest()) {
        // Flash current url to session and redirect to login page
        Session::flash('redirect', URL::full());
        return Redirect::guest('login');
    }
});

And then within the my AuthController.php:

// Try to log the user in.
if (Auth::attempt($userdata)) {

    if ($redirect = Session::get('redirect')) {
        return Redirect::to($redirect);
    } else {
        // Redirect to homepage
        return Redirect::to('your_default_logged_in_page')->with('success', 'You have logged in successfully');
    }
} else {
    // Reflash the session data in case we are in the middle of a redirect 
    Session::reflash('redirect');

    // Redirect to the login page.
    return Redirect::to('login')->withErrors(['password' => 'Password invalid'])->withInput(Input::except('password'));
}

Notice that the 'redirect' session data is reflashed if there is a authentication issue. This keeps the redirect intact during any login mishaps, but should the user click away at any point, the next login process is not disrupted by the session data.

You also need to reflash the data at the point of showing the login form in your AuthController, otherwise the chain is broken:

public function showLogin()
{
    // Reflash the session data in case we are in the middle of a redirect 
    Session::reflash('redirect');

    // Show the login page
    return View::make('auth/login');
}

Solution 11 - Laravel

Use Redirect;

Then use this:

return Redirect::back();

Solution 12 - Laravel

In Laravel 5.8

in App\Http\Controllers\Auth\LoginController add the following method

public function showLoginForm()
{
    if(!session()->has('url.intended'))
        {
            session(['url.intended' => url()->previous()]);
        }
    return view('auth.login');
}

in App\Http\Middleware\RedirectIfAuthenticated replace " return redirect('/home'); " with the following

 if (Auth::guard($guard)->check()) 
    {
        return redirect()->intended();
    }

Solution 13 - Laravel

For Laravel 5.5 and probably 5.4

In App\Http\Middleware\RedirectIfAuthenticated change redirect('/home') to redirect()->intended('/home') in the handle function:

public function handle($request, Closure $next, $guard = null)
{
    if (Auth::guard($guard)->check()) {
        return redirect()->intended('/home');
    }

    return $next($request);
}

in App\Http\Controllers\Auth\LoginController create the showLoginForm() function as follows:

public function showLoginForm()
{
    if(!session()->has('url.intended'))
    {
        session(['url.intended' => url()->previous()]);
    }
    return view('auth.login');
}

This way if there was an intent for another page it will redirect there otherwise it will redirect home.

Solution 14 - Laravel

Laravel now supports this feature out-of-the-box! (I believe since 5.5 or earlier).

Add a __construct() method to your Controller as shown below:

public function __construct()
{
    $this->middleware('auth');
}

After login, your users will then be redirected to the page they intended to visit initially.

You can also add Laravel's email verification feature as required by your application logic:

public function __construct()
{
    $this->middleware(['auth', 'verified']);
}

The documentation contains a very brief example:

It's also possible to choose which controller's methods the middleware applies to by using except or only options.

Example with except:

public function __construct()
{
    $this->middleware('auth', ['except' => ['index', 'show']]);
}

Example with only:

public function __construct()
{
    $this->middleware('auth', ['only' => ['index', 'show']]);
}

More information about except and only middleware options:

Solution 15 - Laravel

if you are using axios or other AJAX javascript library you may want to retrive the url and pass to the front end

you can do that with the code below

   $default = '/';

   $location = $request->session()->pull('url.intended', $default);

    return ['status' => 200, 'location' => $location];

This will return a json formatted string

Solution 16 - Laravel

Did you try this in your routes.php ?

Route::group(['middleware' => ['web']], function () {
    //
    Route::get('/','HomeController@index');
});

Solution 17 - Laravel

       // Also place this code into base controller in contract function,            because ever controller extends base  controller
 if(Auth::id) {
  //here redirect your code or function
 }
if (Auth::guest()) {
       return Redirect::guest('login');
}

Solution 18 - Laravel

Here is my solution for 5.1. I needed someone to click a "Like" button on a post, get redirected to login, then return to the original page. If they were already logged in, the href of the "Like" button was intercepted with JavaScript and turned into an AJAX request.

The button is something like <a href="/like/931">Like This Post!</a>. /like/931 is handled by a LikeController that requires the auth middleware.

In the Authenticate middleware (the handle() function), add something like this at the start:

    if(!str_contains($request->session()->previousUrl(), "/auth/login")) {
        $request->session()->put('redirectURL', $request->session()->previousUrl());
        $request->session()->save();
    }

Change /auth/login to whatever your URL is for logging in. This code saves the original page's URL in the session unless the URL is the login URL. This is required because it appears as though this middleware gets called twice. I am not sure why or if that's true. But if you don't check for that conditional, it will be equal to the correct original page, and then somehow get chanced to /auth/login. There is probably a more elegant way to do this.

Then, in the LikeController or whatever controller you have that handles the URL for the button pushed on the original page:

//some code here that adds a like to the database
//...
return redirect($request->session()->get('redirectURL'));

This method is super simple, doesn't require overriding any existing functions, and works great. It is possible there is some easier way for Laravel to do this, but I am not sure what it is. Using the intended() function doesn't work in my case because the LikeController needed to also know what the previous URL was to redirect back to it. Essentially two levels of redirection backwards.

Solution 19 - Laravel

For Laravel 5.2 (previous versions I did not use)

Paste the code into the file app\Http\Controllers\Auth\AurhController.php

   /**
 * Overrides method in class 'AuthenticatesUsers'
 *
 * @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
 */
public function showLoginForm()
{
    $view = property_exists($this, 'loginView')
        ? $this->loginView : 'auth.authenticate';
    if (view()->exists($view)) {
        return view($view);
    }
    /**
     * seve the previous page in the session
     */
    $previous_url = Session::get('_previous.url');
    $ref = isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '';
    $ref = rtrim($ref, '/');
    if ($previous_url != url('login')) {
        Session::put('referrer', $ref);
        if ($previous_url == $ref) {
            Session::put('url.intended', $ref);
        }
    }
    /**
     * seve the previous page in the session
     * end
     */
    return view('auth.login');
}
/**
 * Overrides method in class 'AuthenticatesUsers'
 *
 * @param Request $request
 * @param $throttles
 *
 * @return \Illuminate\Http\RedirectResponse
 */
protected function handleUserWasAuthenticated(Request $request, $throttles)
{
    if ($throttles) {
        $this->clearLoginAttempts($request);
    }
    if (method_exists($this, 'authenticated')) {
        return $this->authenticated($request, Auth::guard($this->getGuard())->user());
    }
    /*return to the previous page*/
    return redirect()->intended(Session::pull('referrer'));
    /*return redirect()->intended($this->redirectPath()); /*Larevel default*/
}

And import namespace: use Session;

If you have not made any changes to the file app\Http\Controllers\Auth\AurhController.php, you can just replace it with the file from the GitHub

Solution 20 - Laravel

Laravel 5.2

If you are using a another Middleware like Admin middleware you can set a session for url.intended by using this following:

Basically we need to set manually \Session::put('url.intended', \URL::full()); for redirect.

Example

  if (\Auth::guard($guard)->guest()) {
      if ($request->ajax() || $request->wantsJson()) {
         return response('Unauthorized.', 401);
      } else {
        \Session::put('url.intended', \URL::full());
        return redirect('login');
      }
  }

On login attempt

Make sure on login attempt use return \Redirect::intended('default_path');

Solution 21 - Laravel

Larvel 5.3 this actually worked for me by just updating LoginController.php

 use Illuminate\Support\Facades\Session;
 use Illuminate\Support\Facades\URL;


public function __construct()
{
    $this->middleware('guest', ['except' => 'logout']);
    Session::set('backUrl', URL::previous());
}


public function redirectTo()
{
    return Session::get('backUrl') ? Session::get('backUrl') :   $this->redirectTo;
}

ref: https://laracasts.com/discuss/channels/laravel/redirect-to-previous-page-after-login

Solution 22 - Laravel

For Laravel 5.7, You need to make change into:

> Middleware>RedirectIfAuthenticated.php

Change this:

public function handle($request, Closure $next, $guard = null)
    {
        if (Auth::guard($guard)->check()) {
            return redirect('/admin');
        }

        return $next($request);
    }

To this:

public function handle($request, Closure $next, $guard = null)
    {
        if (Auth::guard($guard)->check()) {
            return redirect('/yourpath');
        }

        return $next($request);
    }

> return redirect('/yourpath');

Solution 23 - Laravel

I am using the following approach with a custom login controller and middleware for Laravel 5.7, but I hope that works in any of laravel 5 versions

  • inside middleware

     if (Auth::check()){
         return $next($request);
     }
     else{
       return redirect()->guest(route('login'));
     }
    
  • inside controller login method

     if (Auth::attempt(['email' => $email, 'password' => $password])) {
     return redirect()->intended('/default');
     }
    
  • If you need to pass the intented url to client side, you can try the following

        if (Auth::attempt(['username' => $request->username, 'password' => $request->password])) {
            $intended_url= redirect()->intended('/default')->getTargetUrl();
            $response = array(
           'status' => 'success',
           'redirectUrl' => $intended_url,
           'message' => 'Login successful.you will be redirected to home..', );
           return response()->json($response);
         } else {
             $response = array(
           'status' => 'failed',
           'message' => 'username or password is incorrect', );
          return response()->json($response);
         }
    

Solution 24 - Laravel

First, you should know, how you redirect user to 'login' route:

return redirect()->guest('/signin');

Not like this:

return redirect()->intended('/signin');

Solution 25 - Laravel

This worked for me in laravel 8:

Add this to your LoginController.php:

public function __construct()
{
    session(['url.intended' => url()->previous()]);
    $this->redirectTo = session()->get('url.intended');

    $this->middleware('guest')->except('logout');
}

It will redirect you back 2 times, so to the page you were before login.

Credits goes to @MevlütÖzdemir for the answer!

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJOVView Question on Stackoverflow
Solution 1 - LaravelvFragosopView Answer on Stackoverflow
Solution 2 - LaravelScott ByersView Answer on Stackoverflow
Solution 3 - Laravelgiannis christofakisView Answer on Stackoverflow
Solution 4 - LaraveldabunoView Answer on Stackoverflow
Solution 5 - LaravelMevlütÖzdemirView Answer on Stackoverflow
Solution 6 - LaravelFederico StangoView Answer on Stackoverflow
Solution 7 - LaravelParag BhingreView Answer on Stackoverflow
Solution 8 - LaravelNuruzzaman MilonView Answer on Stackoverflow
Solution 9 - LaravelymkapuriyaView Answer on Stackoverflow
Solution 10 - LaravelJoe RichardsView Answer on Stackoverflow
Solution 11 - Laravelujwal dhakalView Answer on Stackoverflow
Solution 12 - LaravelYann BoyongoView Answer on Stackoverflow
Solution 13 - LaravelDerDareView Answer on Stackoverflow
Solution 14 - LaravelLobsterBazView Answer on Stackoverflow
Solution 15 - LaravelEmmanuel DavidView Answer on Stackoverflow
Solution 16 - LaravelAriosView Answer on Stackoverflow
Solution 17 - Laravelcool programmerView Answer on Stackoverflow
Solution 18 - LaravelBrynn BatemanView Answer on Stackoverflow
Solution 19 - LaravelzdorovoView Answer on Stackoverflow
Solution 20 - LaravelRashedul Islam SagorView Answer on Stackoverflow
Solution 21 - LaravelNomiView Answer on Stackoverflow
Solution 22 - LaravelPrince AhmedView Answer on Stackoverflow
Solution 23 - LaravelNayeem AzadView Answer on Stackoverflow
Solution 24 - LaravelOdilov OybekView Answer on Stackoverflow
Solution 25 - LaravelMarinario AgalliuView Answer on Stackoverflow