jaracas's avatar

Add logic to redirect to different pages on login in Laravel 12 using the built-in auth?

I'm struggling to figure out how to add logic to redirect users after they login to different pages depending on whether they have data in another table or not.

I need to be able to redirect users after they login using the Laravel built-in auth (Vue starter kit not using WorkOS). Where exactly is the logic that determines where the user is sent after logging in? Right now no matter what I do it redirects to /dashboard.

0 likes
10 replies
tykus's avatar

You can bind your own implementation of Laravel\Fortify\Contracts\LoginResponse contract into the Service Container, e.g.

use Laravel\Fortify\Contracts\LoginResponse;
 
/**
 * Register any application services.
 */
public function register(): void
{
    $this->app->instance(LoginResponse::class, new class implements LoginResponse {
        public function toResponse($request)
        {
            // logic to determine URL where the $request->user() should be redirected
   
            return redirect($urlDeterminedAbove);
        }
    });
}

https://laravel.com/docs/12.x/fortify#customizing-authentication-redirects

1 like
jaracas's avatar

I saw that in another thread while trying to solve things, however it never seems to work for me. What am I doing wrong? All it does is redirect me to /dashboard

JussiMannisto's avatar

Those callbacks set the redirection URLs when a guest tries to access an auth protected route, or when an authenticated user tries to access a guest route. They don't define the route after login; that's just a regular redirection response from the login controller.

Check the login method from the controller, and you should see something like this:

return redirect()->intended(route('dashboard'));

Here, the intended() methods redirects the user to the protected URL they tried to access before logging in. If they didn't do that, they get redirected to the default route (dashboard).

Edit. Nevermind — the new starter kits use Fortify, which doesn't publish the login controller. Check this page.

jaracas's avatar

I don't have any auth controllers, in previous versions they were in Controllers\Auth I believe, but now I don't have any. How do I publish them?

JussiMannisto's avatar

I updated my answer since I realized you're using Fortify. Check the edit at the end.

1 like
jaracas's avatar

I've updated my Providers\FortifyServiceProvider.php to:

However it still isn't working

edit: I've made some progress, now I get a modal popup that says "App\Http\Responses\LoginResponse"

My code: App\Http\Responses:

<?php

namespace App\Http\Responses;

use Laravel\Fortify\Contracts\LoginResponse as LoginResponseContract;

class LoginResponse implements LoginResponseContract
{
    /**
     * @param  $request
     * @return mixed
     */
    public function toResponse($request)
    {
        $user = auth()->user();

        if ($user && $user->characters()->count() > 0) {
            return redirect()->intended('/characters');
        }

        return redirect()->intended('/characters/creator');
    }
}

FortifyServiceProvider:

    public function register(): void
    {
        // https://laravel-news.com/override-login-redirects-in-jetstream-fortify
        $this->app->instance(LoginResponseContract::class, LoginResponse::class);
        $this->app->instance(TwoFactorLoginResponse::class, LoginResponse::class); // singleton
    }

edit 2: After some research, I figured out it IS redirecting to where I want, but it re-redirects to /dashboard after that?

jaracas's avatar

I think I fixed it, however Debugbar still says it's hitting /dashboard before /characters/creator.

For people coming here in the future, I had to add:

return Inertia::render('game/character/Create'); 

Then make the vue, add some content to it, then run npm build

maywz's avatar

May I ask the question? So you return the Inertia render page instead of the redirect anymore, right?

maywz's avatar

Just put it here. I found out that if we didn't redirect to the route that return inertia response. It'll throw us to the default route.

Here is my setup

File: app/Providers/FortifyServiceProvider.php

use Laravel\Fortify\Contracts\LoginResponse as LoginResponseContract;
use App\Http\Responses\LoginResponse;

/**
     * Register any application services.
     */
    public function register(): void
    {
       // Register LoginResponse as a singleton to prevent any binding 
        $this->app->singleton(LoginResponseContract::class, LoginResponse::class);
    }

File: app/Http/Responses/LoginResponse.php

class LoginResponse implements LoginResponseContract
{
    public function toResponse($request)
    {
        $user = $request->user();

        if ($user->isCustomer()) return redirect()->route('customer.index');
        return edirect()->route('admin.index');
    }
}

File: app/Http/Controllers/CustomerController.php

public function index()
{
    return Inertia::render('customer/index');
}

and the route file.

Route::get('/admin, function () {
    // This controller or route must return as an Inertia response  
    return Inertia::render('admin/index');
})->name('admin.index');

Route::get('customer', [CustomerController::class, 'index'])->name('customer.index'); 

That's all, I hope it help.

Please or to participate in this conversation.