How to Set a Custom Redirect URL After Login in Laravel Jetstream?

Building web apps is getting easier these days, with new tools coming out every day to help developers get the job done. Laravel Jetstream is one such tool that offers a robust starting point for your Laravel applications. However, sometimes you need to customize certain aspects to fit your specific needs.

In this article, I wanted to share my experience with customizing login and logout redirects in Laravel Jetstream. It's not a framework, just a package that works on top of Laravel to provide authentication scaffolding.

Customizing Login Redirect

To customize where users are redirected after a successful login, you'll need to modify your FortifyServiceProvider. Here's how you can do it:

Open app/Providers/FortifyServiceProvider.php and add the following code to the register method:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Laravel\Fortify\Contracts\LoginResponse;

class FortifyServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->instance(LoginResponse::class, new class implements LoginResponse {
            public function toResponse($request)
            {
                $intended = $request->session()->get('url.intended');
                if ($intended) {
                    return redirect($intended);
                } else {
                    return redirect('/dashboard'); // or any default route
                }
            }
        });
    }

    // ... other methods ...
}

Certainly, I'd be happy to explain that aspect of the custom login redirect and provide some additional context for your readers. Let's enhance that section of your article:

Here's an expanded explanation for the "Customizing Login Redirect" section:

Customizing Login Redirect

To customize where users are redirected after a successful login, you'll need to modify your FortifyServiceProvider. Here's how you can do it:

Open app/Providers/FortifyServiceProvider.php and add the following code to the register method:

<?php

namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Laravel\Fortify\Contracts\LoginResponse;

class FortifyServiceProvider extends ServiceProvider
{
    public function register()
    {
        $this->app->instance(LoginResponse::class, new class implements LoginResponse {
            public function toResponse($request)
            {
                $intended = $request->session()->get('url.intended');
                if ($intended) {
                    return redirect($intended);
                } else {
                    return redirect('/my/dashboard'); // or any default route
                }
            }
        });
    }

    // ... other methods ...
}

In this custom login redirect, we're handling the "intended":

Laravel uses the concept of an "intended" URL to remember where a user was trying to go before they were redirected to the login page. This is particularly useful when a user tries to access a protected route without being authenticated.

$intended = $request->session()->get('url.intended');
if ($intended) {
   return redirect($intended);
} else {
   return redirect('/my/dashboard'); // or any default route
}

Handling the intended URL is optional. If you prefer to always redirect users to a specific route after login, regardless of where they were trying to go, you can simplify the code to:

public function toResponse($request)
{
   return redirect('/my/dashboard'); // or any default route
}

Customizing Logout Redirect

To customize the redirect after a user logs out, add this code to the same register method in your FortifyServiceProvider:

use Laravel\Fortify\Contracts\LogoutResponse;

public function register()
{
    // ... login response code from previous section ...

    $this->app->instance(LogoutResponse::class, new class implements LogoutResponse {
        public function toResponse($request)
        {
            return redirect('/'); // or any route you prefer
        }
    });
}

Testing

By default Laravel Jetstream already has a test suite that tests the login and logout redirects.

To make the test works with this changes you can update the test on file tests/Feature/Auth/AuthenticationTest.php like this:

test('users can authenticate using the login screen', function () {
    $user = User::factory()->create();

    $response = $this->post('/login', [
        'email' => $user->email,
        'password' => 'password',
    ]);

    $this->assertAuthenticated();
    $response->assertRedirect('/my/dashboard');
});

Conclusion

Customizing login and logout redirects in Laravel Jetstream gives you fine-grained control over your application's authentication flow. By implementing these customizations in your FortifyServiceProvider, you can create a more tailored user experience while still leveraging the powerful authentication features provided by Laravel Fortify and Jetstream.