'Laravel 5.5 change unauthenticated login redirect url

In Laravel < 5.5 I could change this file app/Exceptions/Handler to change the unauthenticated user redirect url:

protected function unauthenticated($request, AuthenticationException $exception)
{
    if ($request->expectsJson()) {
        return response()->json(['error' => 'Unauthenticated.'], 401);
    }

    return redirect()->guest(route('login'));
}

But in Laravel 5.5 this has been moved to this location vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php so how can I change it now? I don't want to change stuff in the vendor directory encase it gets overridden by composer updates.

protected function unauthenticated($request, AuthenticationException $exception)
{
    return $request->expectsJson()
                ? response()->json(['message' => 'Unauthenticated.'], 401)
                : redirect()->guest(route('login'));
}


Solution 1:[1]

But in Laravel 5.5 this has been moved to this location vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php so how can I change it now? I don't want to change stuff in the vendor directory encase it gets overridden by composer updates.

It's just the case that the function is not there by default anymore.

You can just override it as you did in 5.4. Just make sure to include

use Exception;
use Request;
use Illuminate\Auth\AuthenticationException;
use Response;

in the Handler file.

For Example my app/Exceptions/Handler.php looks somewhat like this:

<?php
    namespace App\Exceptions;
    use Exception;
    use Request;
    use Illuminate\Auth\AuthenticationException;
    use Response;
    use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
    class Handler extends ExceptionHandler
    {
        (...) // The dfault file content
        /**
         * Convert an authentication exception into a response.
         *
         * @param  \Illuminate\Http\Request  $request
         * @param  \Illuminate\Auth\AuthenticationException  $exception
         * @return \Illuminate\Http\Response
         */
         protected function unauthenticated($request, AuthenticationException $exception)
         {
            return $request->expectsJson()
                    ? response()->json(['message' => 'Unauthenticated.'], 401)
                    : redirect()->guest(route('authentication.index'));
    }
}

Solution 2:[2]

Here's how I solved it. In render function I caught exception class. And in case if it's Authentication exception class I wrote my code for redirect (the code I would write in unauthenticated function in previous version).

public function render($request, Exception $exception)
{
    $class = get_class($exception);

    switch($class) {
        case 'Illuminate\Auth\AuthenticationException':
            $guard = array_get($exception->guards(), 0);
            switch ($guard) {
                case 'admin':
                    $login = 'admin.login';
                    break;
                default:
                    $login = 'login';
                    break;
            }

            return redirect()->route($login);
    }

    return parent::render($request, $exception);
}

Solution 3:[3]

But in Laravel 5.5 this has been moved to this location vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php so how can I change it now? I don't want to change stuff in the vendor directory encase it gets overridden by composer updates.

We need to just include the use Illuminate\Auth\AuthenticationException;

and then it works as in laravel 5.4

Solution 4:[4]

For Laravel ( 5.4, 6, 7, 8.x )

I don't want to change in the vendor directory encase it gets overridden by composer updates. You can just override it as you did in 5.4. Just make sure to include.

File: App\Exceptions\Handler.php

Copy this below code and past to your app\Exception\Handler

<?php

namespace App\Exceptions;

use Request;
use Illuminate\Auth\AuthenticationException;
use Response;

use Illuminate\Support\Arr;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
use Throwable;

class Handler extends ExceptionHandler
{
    /**
     * A list of the exception types that are not reported.
     *
     * @var array
     */
    protected $dontReport = [
        //
    ];

    /**
     * A list of the inputs that are never flashed for validation exceptions.
     *
     * @var array
     */
    protected $dontFlash = [
        'password',
        'password_confirmation',
    ];

    /**
     * Report or log an exception.
     *
     * @param  \Throwable  $exception
     * @return void
     *
     * @throws \Exception
     */
    public function report(Throwable $exception)
    {
        parent::report($exception);
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Throwable  $exception
     * @return \Symfony\Component\HttpFoundation\Response
     *
     * @throws \Throwable
     */
    public function render($request, Throwable $exception)
    {
        return parent::render($request, $exception);
    }
        protected function unauthenticated($request, AuthenticationException $exception)
    {
        // return $request->expectsJson()
        //             ? response()->json(['message' => $exception->getMessage()], 401)
        //             : redirect()->guest(route('login'));

        if($request->expectsJson()) {
            return response()->json(['message' =>  $exception->getMessage()],401);
        }

        $guard = Arr::get($exception->guards(), 0);

        switch ($guard) {
            case 'admin':
            $login = 'admin.login';
            break;
            case 'vendor':
            $login = 'vendor.login';
            break;
            
            default:
            $login = 'login';
            break;
        }

        return redirect()->guest(route($login));

    }
}

Solution 5:[5]

The standard exception handler uses a named route.

So, you just define your route to use that name.

So, in your routes/web.php file, just add the line:

Route::get('mylogin', 'MyLoginController@showLoginForm')->name('login');

The name('login') bit gives this route a name, so the unauthenticated exception will use this route.

You don't need to bother messing around making your own exception handler, or modifying the standard exception handler.

The named routes used by the boilerplate 'auth' code can be found in the vendor/laravel/framework/src/Illuminate/Routing/Router.php file, in the auth() function. (login, logout, register, password.request, password.email and password.reset). These routes are added when you use the Route::auth(); line in the route file.

Solution 6:[6]

In newer versions of Laravel, you should go to

app/Http/Middleware/Authenticate.php

Now you can edit the function and redirect it to wherever you want:

protected function redirectTo($request)
{
    if (! $request->expectsJson()) {
        return route('login');
    }
}

Hope it helps.

Solution 7:[7]

Just add a route for login in routes file:

Route::get('/login', [
   'uses' => 'UserController@getSignin',
   'as' => 'login'
]);

Solution 8:[8]

Replace Your app\Exceptions\Handler.php code with the following....

<?php

namespace App\Exceptions;

use Exception;
use Illuminate\Auth\AuthenticationException;
use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;

class Handler extends ExceptionHandler
{
    /**
     * A list of the exception types that are not reported.
     *
     * @var array
     */
    protected $dontReport = [
        //
    ];

    /**
     * A list of the inputs that are never flashed for validation exceptions.
     *
     * @var array
     */
    protected $dontFlash = [
        'password',
        'password_confirmation',
    ];

    /**
     * Report or log an exception.`enter code here`
     *
     * @param  \Exception  $exception
     * @return void
     */
    public function report(Exception $exception)
    {
        parent::report($exception);
    }

    /**
     * Render an exception into an HTTP response.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  \Exception  $exception
     * @return \Illuminate\Http\Response
     */
    public function render($request, Exception $exception)
    {
        return parent::render($request, $exception);
    }

    protected function unauthenticated($request, AuthenticationException $exception)
    {
        if ($request->expectsJson()) {
            return response()->json(['message' => $exception->getMessage()], 401);
        }


        $guard = array_get($exception->guards(),0);
        switch ($guard) {
            case 'admin':
                $login = 'admin.login';
                break;

            default:
                $login = 'login';
                break;
        }

        return redirect()->guest(route($login));
    }
}

Solution 9:[9]

Copy this to your app\Exception\Handler

use Request;
use Illuminate\Auth\AuthenticationException;
use Response;

protected function unauthenticated($request, AuthenticationException $exception){
  if ($request->expectsJson()) {
     return response()->json(['message' => $exception->getMessage()], 401);
  }

  $guard = array_get($exception->guards(),0);

  switch ($guard) {
    case 'admin':
        return redirect()->guest(route('admin.login'));
       break;

     default:
       return redirect()->guest(route('login'));
      break;
  }
}

Solution 10:[10]

For Laravel 7.x+

===========**top add class:**================
use Illuminate\Auth\AuthenticationException;

use Illuminate\Support\Arr;
=======================================

public function render($request, Throwable $exception)
    {
        if($exception instanceof AuthenticationException){
            $guard = Arr::get($exception->guards(), 0);
            switch($guard){
                case 'admin':
                    return redirect(route('admin.login'));
                    break;
                default:
                    return redirect(route('login'));
                    break;
            }
        }

        return parent::render($request, $exception);
    }

Solution 11:[11]

For Laravel verison 7.*

File: App\Exceptions\Handler.php

use Illuminate\Support\Arr; //Top Class

use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;

public function render($request, Throwable $exception) {

    // for Multi AUth guard

    if($exception instanceof AuthenticationException){
        $guard = Arr::get($exception->guards(), 0);
        switch($guard){
            case 'admin':
                return redirect(route('admin.login'));
                break;
            default:
                return redirect(route('login'));
                break;
        }
    }



    return parent::render($request, $exception);
}

Solution 12:[12]

Other than overriding, you could directly make changes in Handler.php to the existing function unauthenticated located at vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php to redirect to intended route based on guards.

/**
 * Convert an authentication exception into a response.
 *
 * @param  \Illuminate\Http\Request  $request
 * @param  \Illuminate\Auth\AuthenticationException  $exception
 * @return \Illuminate\Http\Response
 */
protected function unauthenticated($request, AuthenticationException $exception)
{


    $guard = array_get($exception->guards(),0);
    switch ($guard) {
        case 'admin':
            return $request->expectsJson()
                        ? response()->json(['message' => $exception->getMessage()], 401)
                        : redirect()->guest(route('admin.login'));
            break;

        default:
            return $request->expectsJson()
                        ? response()->json(['message' => $exception->getMessage()], 401)
                        : redirect()->guest(route('login'));
            break;
    }
}