Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

daugaard47's avatar

Redirect to Intended URL Jetstream Fortify

I'm currently moving my side project, built on the Tall stack preset over to Jetstream and all is good. The only issue I'm running into is Fortify's Auth system. I have one important section on my site that requires Guests to login in.

//TEST PAGE
@guest
    Please login or register
    <a href="{{ route('login') }}">Login</a>
    <a href="{{ route('register') }}">Register</a>
@endif
    Now you can proceed.

Once they login/register I need them to return back to this page. But with Jetstream & Fortify there is no Login/Register controller or Action available. They are hidden in the Vendor Files =/

If the Route is protected with middleware I can get it to work, but in this "use case" it's not acceptable for this section.

//Redirects Back To Intended URL
Route::middleware(['auth:sanctum', 'verified'])->get('test',[App\Http\Controllers\TestController::class, 'test'])->name('test');

//Does NOT Redirects Back To Intended URL
Route::get('test',[App\Http\Controllers\TestController::class, 'test'])->name('test');

JetStream: Middleware\RedirectIfAuthenticated.php

    public function handle($request, Closure $next, ...$guards)
    {
        $guards = empty($guards) ? [null] : $guards;

        foreach ($guards as $guard) {
            if (Auth::guard($guard)->check()) {
               return Redirect::intended('/');
               // return redirect(RouteServiceProvider::HOME);
            }
        }
        return $next($request);
    }

On Laravel 7 Tallstack it worked great like this with the Livewire Login Component:

    public $previousUrl='/';

    public function mount ()
    {
        $this->previousUrl=\session('_previous.url');
    }


    public function authenticate()
    {
        $credentials = $this->validate([
            'email' => ['required', 'email'],
            'password' => ['required'],
        ]);
        if (!Auth::attempt($credentials, $this->remember)) {
            $this->addError('email', trans('auth.failed'));
            return;
        }
        redirect()->to($this->previousUrl);
      //  redirect(route('home'));
    }

I realize Jetstream is brand new to the scene and I probably should have waited, but this is the only thing holding me back.

I did find this Workaround/Hack that might possibly work, but really hoping for a better solution Link: https://github.com/laravel/jetstream/issues/102#issuecomment-689664204

If someone could please help me get this working I would really appreciate it.

0 likes
24 replies
Nakov's avatar

As far as I know the only way to change the landing page after login is through the fortify config page, but you won't be able to redirect to the intended page.

The only way possible is to manually handle the login as shown here: https://laravel.com/docs/8.x/authentication#authenticating-users

And for the register action you can still land on the default page, as there should be no intended action anyway before the user is registered.

daugaard47's avatar

So here it says for Laravel 8:

Manually Authenticating Users:

Note that you are not required to use the authentication controllers included with Laravel Jetstream

BUT In Jetstream you are required to use Fortify correct? There is no Auth facade in JetStream

I see on Twitter, Taylor mentions adding more support, but I still don't see this helping in my case with the Login and Register Redirects. Am I missing something?

https://github.com/laravel/fortify/issues/17

With the new options listed above by Taylor is this an option now. Apologize for my lack of knowledge. Fortify is throwing me for a loop. Thank you for your help.

Snapey's avatar

Perhaps;

Create a second route using the same view.

Protect this second route with auth middleware

ask the guest to 'login' but the button will take them to the second route. This will become the intended route but they will be taken to login screen. They complete login and then go to the second route which is showing the same view as the first route.

daugaard47's avatar

@snapey Wow, Nice job! Looks like exactly what I need. Thank you for helping and making/sharing this great resource.

Snapey's avatar

@jlrdw not sure how this could be a change to jetstream since this is user implementation detail. Perhaps a hint in the docs only.

@daugaard47 mark it answered if you are happy to.

daugaard47's avatar

@snapey Your solution worked great. Thank you!

I agree with @jlrdw, You should submit it for the docs at least.

daugaard47's avatar

@snapey @jlrdw I thought I had this figured out, but still running into an issue redirecting back to the correct page.

Without using any middleware I need the login and register forms to redirect back to the page where the user accesses the login or register pages.

Example:

  1. User Enters homepage > pricing page
  2. On Pricing Page user chooses option A, B or C
  3. User chooses A
  4. User goes to Pricing Page A and it says you need to login/register to continue
  5. User Goes to Login or Register

Need the user to return Back to Pricing Page A on Login or Registration

I'm currently trying to convert the logic I was using in the Livewire Login Component listed above. That work perfect.

class LoginResponse implements LoginResponseContract {

    public $previousUrl='/';

    public function toResponse($request) {

       $previousUrl=\session('_previous.url');

 // dd($previousUrl); // This returns "https://mysite.test/login"
//  return redirect('test-page'); // This returns "https://mysite.test/test-page"

        return redirect()->to($previousUrl);

    }

I keep getting redirected back to the login page. Not sure how this was working in Livewire? If I return a hardcoded route return redirect('test-page'); that works fine.

In this example it seems I need to return back 2 pages. (Going backwards: : login > pricing page A)

Any Idea how to accomplish this?

1 like
jlrdw's avatar

When I tested intended with @snapey solution it worked. You may need a custom "intended" in your case.

They start on a page not requiring a login, then click page requiring login, could catch intended in session, and build a redirect via session variable.

Could always use a modal for login I suppose also.

1 like
Snapey's avatar

As @jlrdw says, the original login response returns to the intended route.

This was my initial proposed solution, to have a separate route with the same view. Protect the separate route with the auth middleware so that users are caught as they transition.

Another approach may be to store something in session in the controller of the page when they are not logged in, that you can refer to when they complete login. If this value is in session then remove it and direct them to that page (your own version of the intended route).

Just watch for the session being swapped when they login though.

braffzachlin's avatar

@snapey Why did you place the class in the JetstreamServiceProvider?

Here's what I did:

In "app\Providers\FortifyServiceProvider.php"

...
use App\Http\Responses\LoginResponse;
...

public function register()
{
    $this->registerResponseBindings();
}

protected function registerResponseBindings()
{
    $this->app->singleton(LoginResponseContract::class, LoginResponse::class);
}

In "app\Responses\LoginResponse.php"

<?php

namespace App\Http\Responses;

use Laravel\Fortify\Contracts\LoginResponse as LoginResponseContract;

class LoginResponse implements LoginResponseContract
{
    /**
    * Create an HTTP response that represents the object.
    *
    * @param  \Illuminate\Http\Request  $request
    * @return \Symfony\Component\HttpFoundation\Response
    */
    public function toResponse($request)
    {
        $role = \Auth::user()->role;
    
        if ($request->wantsJson()) {
            return response()->json(['two_factor' => false]);
        }

        switch ($role) {
            case 'admin':
                return redirect()->intended(config('fortify.home'));
            case 'host':
                return redirect()->intended('/host/dashboard');
            default:
                return redirect('/');
        }
    }
}
3 likes
daugaard47's avatar

Okay I finally figured it out. Now, no matter where you are on the website. When you click the login or register link and login or register you will be redirected back to that original page.

Example:

  1. I'm a guest and I'm on the Privacy Policy page.
  2. I decide I want to login or register and click the link in the navigation
  3. I will now be redirected back to the Privacy Policy Page.

Here is the code. Hopefully someone will find it useful.

App\Providers\JetstreamServiceProvider.php (Thanks to Mr. Otwell and @snapey )

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

        Jetstream::deleteUsersUsing(DeleteUser::class);

//Get Session Link for Login View

        Fortify::loginView(function () {
            if (session('link')) {
                $myPath = session('link');
                $loginPath = url('/login');
                $previous = url()->previous();

                if ($previous = $loginPath) {
                    session(['link' => $myPath]);
                } else {
                    session(['link' => $previous]);
                }
            } else {
                session(['link' => url()->previous()]);
            }
            return view('auth.login');
        });

//Get Session Link for Registration View

        Fortify::registerView(function () {
            if (session('link')) {
                $myPath = session('link');
                $registerPath = url('/register');
                $previous = url()->previous();

                if ($previous = $registerPath) {
                    session(['link' => $myPath]);
                } else {
                    session(['link' => $previous]);
                }
            } else {
                session(['link' => url()->previous()]);
            }
            return view('auth.register');
        });

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

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

Responses/LoginResponse.php & RegisterResponse.php

namespace App\Http\Responses;

use Laravel\Fortify\Contracts\LoginResponse as LoginResponseContract;

class LoginResponse implements LoginResponseContract {

    public function toResponse($request) {
        return redirect(session('link'));
    }
}

Could probably clean up that duplicate code in the JetstreamServiceProvider, but other than that it works great.

Thanks for the help everyone!

4 likes
dessimoni's avatar

Works great!

I've Just changed

session(['link' => url()->previous()]);

to

session(['link' => session('url.intended')]);

keeping the original redirect to intended page behaviour

Treesoft's avatar

@snapey

thx for the great work. Do you have a solution for redirecting after registration as well? ;)

Snapey's avatar

@treesoft

The principle is the same, but you replace the RegisterResponse class with one of your own

        // register new RegisterResponse
        $this->app->singleton(
            \Laravel\Fortify\Contracts\RegisterResponse::class,
            \App\Http\Responses\RegisterResponse::class
        );
1 like
Nmason's avatar

Thanks @Snapey for sharing - this worked perfectly for me for both the LoginResponse & registerResponse.

dgc223's avatar

Thanks all, I've spent weeks on this issue and finally close to a solution thanks to @snapey and @daugaard47 . Question about the new register response, I got that set up but now when user registers, they are logged in automatically, I don't know how to get the verification email step required like it was before. Jetstream/Fortify are still sending the email to 'verify', but the user already is logged in after submitting the new Register class. Does anyone have the code I need to put in there, to make it require the verification as it did before?

Also hoping that Laravel is looking at this and will make a standard functionality in the future. Thanks again to all for helping a code newbie :)

Snapey's avatar

@dgc223

This is standard Laravel behaviour for verify email. The user is logged in and must be logged in to verify their email.

You will need to log the user out, and create different verification routes if you want the user to be blocked from logging in until they have verified.

1 like
dgc223's avatar

According to the docs, https://laravel.com/docs/8.x/verification

"Many web applications require users to verify their email addresses before using the application. Rather than forcing you to re-implement this feature by hand for each application you create, Laravel provides convenient built-in services for sending and verifying email verification requests."

That was how it worked before I made this update, so just trying to see how I can get the register class to follow that same logic as before.

Please or to participate in this conversation.