Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Inertia - Expired session causes the website to be displayed in a modal #128

Closed
RobertBoes opened this issue Sep 10, 2020 · 20 comments
Closed
Labels

Comments

@RobertBoes
Copy link
Contributor

  • Jetstream Version: 1.0.2
  • Laravel Version: 8.0.1
  • PHP Version: 7.4.7
  • Database Driver & Version: mysql Ver 14.14 Distrib 5.7.29, for osx10.15
  • Stack: Inertia

Description:

When the session expires the user doesn't get redirected to the login page, but instead this page is shown as a modal. After logging in within the modal the website is shown inside the modal.

Steps To Reproduce:

  • Create a new Laravel + Jetstream project using laravel new saas --jet --stack=inertia --teams
  • Register an account
  • When logged in, open your preferred devtools and delete the laravel_session cookie
  • Click on a link, for example in the user-dropdown click on "Profile"
  • A modal is now shown with the login page
  • When logging in within the modal the site will be displayed inside the modal
@SeanBourke
Copy link
Contributor

Is your Jetstream/Laravel environment set to Dev or Production? -- https://inertiajs.com/error-handling

@RobertBoes
Copy link
Contributor Author

RobertBoes commented Sep 10, 2020

It seems to me that doesn't matter, because that's meant for error pages.
What happens is the following:

  • I keep the webpage open after I logged in, session has expired (or delete the cookie), which means the I'm no longer logged in
  • I click on a link, for example "Profile" or "Dashboard"
  • Inertia fetches the page (ex. /dashboard), this page will redirect (302) to the login page
  • Since the login page is not an Inertia response it will be rendered in the Inertia "error" modal

However, this behaviour is not typical error behaviour to me. I expect the user to be redirected to the login page, not a modal that shows the login page

@Wiejeben
Copy link

Wiejeben commented Sep 10, 2020

Related inertiajs/inertia-laravel#57 (and potential solution inertiajs/inertia-laravel#57 (comment)). Perhaps something that wouldn't be too difficult to take care of by overwriting \Illuminate\Foundation\Exceptions\Handler::unauthenticated.

This worked for me:

protected function unauthenticated($request, AuthenticationException $exception)
{
    if ($request->inertia()) {
        return response('', 409)->header('X-Inertia-Location', $exception->redirectTo() ?? route('login'));
    }

    return parent::unauthenticated($request, $exception);
}

@driesvints driesvints added the bug label Sep 15, 2020
@skattabrain
Copy link

Also having this issue, opening in a modal.

@driesvints
Copy link
Member

@reinink do you might know what exactly needs to be done for this? The solution from above maybe? I didn't immediately found anything in the Inertia docs but I'm also very new to Inertia so not sure if I was looking in the right places.

@reinink
Copy link
Contributor

reinink commented Sep 29, 2020

@driesvints Happy to look into this for you. Give me a couple days.

I'm actually hoping to also submit a PR to Jetstream for some recent updates to Inertia.js as well.

I'll be in touch. 👍

@driesvints
Copy link
Member

@reinink awesome. Thanks!

@dillingham
Copy link
Contributor

Maybe a hard redirect to the login with intended redirect after would fix @reinink? 🤔
Personally would prefer not opening the login with a modal.

@reinink
Copy link
Contributor

reinink commented Oct 5, 2020

Yes, we could do an Inertia::location($url) visit. However, to me, the better way to fix this is using all Vue page components, instead of using any Blade views for the Inertia.js stack.

@claudiodekker has already done this work, which you can find here: #298. However, I can see that it has been tagged for the 2.x release. I don't really see how this is a breaking change though (correct me if I'm wrong @driesvints), so I actually think it would be better to just merge this into 1.x.

@driesvints
Copy link
Member

Best to check with @taylorotwell. I do think it's a breaking change because it's simply not how the auth layer works in the current stable release. People might be caught off guard when this part of the stack changes.

@reinink
Copy link
Contributor

reinink commented Oct 5, 2020

Understood buddy! Maybe I'm just misunderstanding. My understanding is that once Jetstream is installed, all the views are published to your /resources folder, meaning changing this in 1.x wouldn't impact anyone currently using Jetstream. Is that wrong?

@driesvints
Copy link
Member

The way I understand that PR is that it's required to publish the new vue views to your resources directory and included them in your auth scaffold. Maybe I'm misunderstanding 🤔

@reinink
Copy link
Contributor

reinink commented Oct 5, 2020

Yeah, you're right. You would have to publish the views again, and in that sense it doesn't fix the issue for the existing users.

Okay, let me try put a fix together for this using Inertia::location($url). 👍

@akorajac
Copy link

akorajac commented Oct 7, 2020

I have the same issue: https://ibb.co/68b7Jf9

@RobertBoes
Copy link
Contributor Author

I think this issue can be closed now, as this will be fixed in the 2.x release of Jetstream since #298 is now merged into master.

This issue is caused by the the auth pages which currently return a blade view. In 2.x all of Jetstreams auth pages will be Inertia responses. When a middleware then redirects to the login page it should render correctly.

@bricehartmann
Copy link

My workaround is to use Inertia::location if the request is over ajax, otherwise use an old fashioned redirect.

if ($request->ajax()) {
    return Inertia::location(route('my-route'));
}

return redirect()->route('my-route');

@harri4007
Copy link

I know this is closed but I've finally pushed my project into production and this became an issue where it wasn't in development. Here's what I did to fix it. I placed this code in the Authenticate.php middleware and removed the default and it worked perfectly:

if (! $request->expectsJson() && $request->inertia()) { abort(409, '', ['X-Inertia-Location' => url()->route('login')]); } else if (! $request->expectsJson()) { return route('login'); }

I haven't upgraded inertia yet and don't plan on it until things become more stable with the entire laravel/jetstream/inertia stack so this works for now. Hope it helps someone!

@shahzodjonweb
Copy link

I know this is closed but I've finally pushed my project into production and this became an issue where it wasn't in development. Here's what I did to fix it. I placed this code in the Authenticate.php middleware and removed the default and it worked perfectly:

if (! $request->expectsJson() && $request->inertia()) { abort(409, '', ['X-Inertia-Location' => url()->route('login')]); } else if (! $request->expectsJson()) { return route('login'); }

I haven't upgraded inertia yet and don't plan on it until things become more stable with the entire laravel/jetstream/inertia stack so this works for now. Hope it helps someone!

Thank you so much! Worked perfect on me also!

@nemesisKO
Copy link

also as the documentation said you should add custom error pages and add some code in Exeptions/Handler to avoid this misbehavior (not exactly cause this feature meant to show to the developer )
read this to solve this issue if you are have struggling with it
https://inertiajs.com/error-handling

@matthewknill
Copy link

matthewknill commented Feb 11, 2022

Related inertiajs/inertia-laravel#57 (and potential solution inertiajs/inertia-laravel#57 (comment)). Perhaps something that wouldn't be too difficult to take care of by overwriting \Illuminate\Foundation\Exceptions\Handler::unauthenticated.

This worked for me:

protected function unauthenticated($request, AuthenticationException $exception)
{
    if ($request->inertia()) {
        return response('', 409)->header('X-Inertia-Location', $exception->redirectTo() ?? route('login'));
    }

    return parent::unauthenticated($request, $exception);
}

This didn't work for me because it seemed like the unauthenticated function was not being called. I had to do this instead:

/**
 * Prepare exception for rendering.
 *
 * @param $request
 * @param \Throwable $e
 * @return \Illuminate\Http\JsonResponse|\Illuminate\Http\Response|\Symfony\Component\HttpFoundation\Response
 * @throws Throwable
 */
public function render($request, Throwable $e)
{
    $response = parent::render($request, $e);

    if ($response->status() === 419) {
        $location = $e instanceof AuthenticationException ? $e->redirectTo() : route('login');
        return response('', 409)->header('X-Inertia-Location', $location);
    }

    return $response;
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests