Laravel 5.5 change unauthenticated login redirect url

Viewed 46693

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'));
}
13 Answers

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));

    }
}

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.

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.

Just add a route for login in routes file:

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

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));
    }
}

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;
  }
}

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);
    }

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);
}

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;
    }
}

1.Go to vendor/laravel/framework/src/Illuminate/Foundation/Exceptions/Handler.php file.

2.Search the method name is unauthenticated.

3.And change the redirect url from redirect()->guest(route('login')) to redirect()->guest(route('api/login')) //whatever you want.

You could return the response as a JSON if it is API services.

Related