How to provide different login redirects when using Laravel Fortify and Jetstream

Fortify, a new back-end package for offering user authentication services, was released with Laravel 8. There have been some concerns that the authentication procedure can no longer be customized because this constitutes a significant change from the controller with traits approach utilized in earlier versions.

Naturally, it would be improbable given the framework's age and prior experiences to create a framework that does not allow for overriding default behavior.

Let's say that based on some user attribute, we need to reroute the user as they log in. How might this be possible with Fortify?

When the Laravel\Fortify\FortifyServiceProvider boots, the hooks that we need are tied into the container. We can re-bind a different class, where we will put our business logic, within our own code.

Create our own Login Response Class

  1. Create a folder under app\Http called Responses
  2. Create a file LoginResponse.php
<?php

namespace App\Http\Responses;

use Illuminate\Support\Facades\Auth;
use Laravel\Fortify\Contracts\LoginResponse as LoginResponseContract;

class LoginResponse implements LoginResponseContract
{

    public function toResponse($request)
    {
        
        // below is the existing response
        // replace this with your own code
        // the user can be located with Auth facade
        
        return $request->wantsJson()
                    ? response()->json(['two_factor' => false])
                    : redirect()->intended(config('fortify.home'));
    }

}

For Example

<?php

namespace App\Http\Responses;

use Illuminate\Support\Facades\Auth;
use Laravel\Fortify\Contracts\LoginResponse as LoginResponseContract;

class LoginResponse implements LoginResponseContract
{

    public function toResponse($request)
    {
        return $request->wantsJson()
                    ? response()->json(['two_factor' => false])
                    : redirect()->intended(
                        auth()->user()->is_admin ? route('admin.dashboard') : route('dashboard')
                    );
    }

}

Note: Here, the intended() method suggests that you want the user to return to the page they were on before logging out, and if that page can't be found, then redirect to the page you specify. Use the route() function rather than meant() if you wish to always redirect to the pages you specify, as demonstrated below:

<?php

namespace App\Http\Responses;

use Illuminate\Support\Facades\Auth;
use Laravel\Fortify\Contracts\LoginResponse as LoginResponseContract;

class LoginResponse implements LoginResponseContract
{

    public function toResponse($request)
    {
        return $request->wantsJson()
                    ? response()->json(['two_factor' => false])
                    : redirect()->route(
                        auth()->user()->is_admin ? ('admin.dashboard') : ('dashboard')
                    );
    }

}

Make Laravel use our new Response Class

The Singleton that Fortify had previously registered has been replaced with this new class. 

Edit the JetstreamServiceProvider in your app\Providers folder;

Add a reference to your new response class in the boot method. Your new response will be called once the login process is finished (and the user has successfully authenticated).

    public function boot()
    {
        $this->configurePermissions();

        Jetstream::deleteUsersUsing(DeleteUser::class);

        // register new LoginResponse
        $this->app->singleton(
            \Laravel\Fortify\Contracts\LoginResponse::class,
            \App\Http\Responses\LoginResponse::class
        );
    }

Two Factor Authentication

You must additionally catch the TwoFactorLoginResponse if you utilize 2FA with Jetstream. employ the same strategy;


        // register new TwofactorLoginResponse
        $this->app->singleton(
            \Laravel\Fortify\Contracts\TwoFactorLoginResponse::class,
            \App\Http\Responses\LoginResponse::class
        );

You can return the same response, or create an additional response if you want different behaviour for users that login using 2FA.

Conclusion

By doing this, you can change the default Jetstream login action so that your custom pages are opened instead of the ones Jetstream and Fortify have pre-selected.

I sincerely hope that the majority of you find the approach covered here to be helpful. Thank you for reading, and please feel free to leave any comments or questions in the comments section below.

Post a Comment

0 Comments