cas icon indicating copy to clipboard operation
cas copied to clipboard

How to implement logout using Inertia-VueJS - Laravel

Open arhen opened this issue 3 years ago • 4 comments

Im trying to implement logout via request because my application is SPA. But got CORS-Policy using function logoutWithRedirectService in the backend. Is there any how-to for SPA apps?

arhen avatar May 19 '21 04:05 arhen

I'd recommend checking with https://github.com/apereo/cas since this package leverages and abstracts Apereo CAS. If you find out, please post it back to help others.

subfission avatar Jun 23 '21 09:06 subfission

I use the package in many Laravel-Jetstream-InertiaJS-VueJS Apps. I could share the workflow if interested.

coolsam726 avatar Oct 05 '21 07:10 coolsam726

i have same problem, can you share your workflow @coolsam726 ?

thanks

alfarioekaputra avatar Nov 18 '21 07:11 alfarioekaputra

Here is the setup that I use for my Inertia.js setup: NB: cas.logout is configured in the web guard, not api. Background:

  • I maintain a local copy of users in the users table, so my cas service is purely for authentication. Returns a username.
  • Upon CAS Login, I can obtain the username of the authenticated CAS user and find a user in my local table with that username and log them in automatically. Here is my login route, which also acts as my CAS service callback:
private static function casLogin(Request $request)
    {
        if (cas()->isAuthenticated()) {
            $username = cas()->user();
        } else {
            // Redirect to cas login page and exit
            cas()->authenticate();
            return false;
        }
        // At this stage the CAS session exists and a username has been retrieved for the logged in user.
        \Log::info("User: $username is being logged in");
        try {
            $user = User::whereUsername($username)->first(); // returns null if no user.
            if (!$user) {
                abort(404, "User not found");
            }
            \Log::info("Logging in $user->username");
// If not using fortify, this is how you would go:
//            \Auth::login($user);
//            \Log::info("sending login response");
//            return $this->sendLoginResponse($request);
// If using Fortify for authentication, --> Reach out for more info on how to implement the login pipeline.
            return $user;
        } catch (\Throwable $exception) {
            \Log::error($exception);
//            return $this->sendFailedLoginResponse($request);
            return null;
        }
    }

Logout With the above login logic in place, here is how you logout:

    public function casLogout(Request $request): \Illuminate\Http\Response
    {
        $this->guard->logout();
        $request->session()->invalidate();
        $request->session()->regenerateToken();
        // cas()->logout();
        return Inertia::location('MY_CAS_LOGOUT_URL_HERE'); // <------- Important in order for the client to redirect to the logout service and logout the cas session.
    }

Calling logout route from the Inertia SPA client

<template>
      <button @click.prevent='logout'>LOGOUT</button>
</template>
<script>
export default {
    methods: {
         logout()  {
            const vm = this;
            const win = window.open(this.route("cas.logout"), "_blank");
            setTimeout(function () {
                win.close();
                vm.$inertia.reload();
            }, 1000);
         }
    }
}
</script>

What will happen: Once you click the button, the system will logout your local session, then open a separate window for 1000ms (You can adjust this to your preference), long enough for it to redirect to the CAS logout page and logout the cas session, then close the window automatically.

If you need any clarifications, do reach out.

coolsam726 avatar Nov 18 '21 12:11 coolsam726