Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Vue.js / Laravel - Handle logout correctly

I am currently trying to create a simple SPA using Vue and Laravel. I've got the basics to work - users can register and login.

I just can't figure out how to create a logout function.

This is what I currently have:

AuthController.php:

public function logout()
{
        $accessToken = auth()->user()->token();

        $refreshToken = DB::table('oauth_refresh_tokens')
        ->where('access_token_id', $accessToken->id)
        ->update([
            'revoked' => true
        ]);

        $accessToken->revoke();

        return response()->json(['status' => 200]);
}

routes/api.php:

Route::middleware('auth:api')->group(function () {
    Route::post('/logout', 'API\AuthController@logout');
    Route::get('/get-user', 'API\AuthController@getUser');
});

Right now, this is what I have tried to do:

Layout.vue:

methods: {
            logout() {
                axios.post('/api/logout').then(response => {
                    this.$router.push("/login")

                }).catch(error => {
                    location.reload();
                });
            }
 }

Which calls my logout function in Auth.js:

logout() {
    localStorage.removeItem('token')
    localStorage.removeItem('expiration')
}

However, when users click on the logout function, they are not logged out immediately (redirected to the login page) - they can still browse "user only pages".

I have to refresh the page before I am properly logged out.

Can anyone assist me with this? Is this even the right approach to a "secure" logout function?

like image 445
oliverbj Avatar asked Aug 25 '18 21:08

oliverbj


2 Answers

That's a bit old, however, I've just started with Laravel/Vue and managed to do this quite simple. Using the integrated auth from Laravel, you could just simulate the logout from app.blade.php like so:

<b-dropdown-item href="#" onclick="event.preventDefault(); document.getElementById('logout-form').submit();">Sign Out</b-dropdown-item> //that's instead of a regular <a> tag
<b-form id="logout-form" action="logout" method="POST" style="display: none;">
   <input type="hidden" name="_token" :value="csrf">
</b-form>

You'll need to have the csrf token passed through data in your script in order for it to work like so:

export default {
 data() {
   return {
     csrf: document.querySelector('meta[name="csrf-token"]').getAttribute('content')
   }
 },
 methods: {
   submit : function(){
     this.$refs.form.submit();
   }
 }
}

As well as adding a meta csrf in your head (blade.php file) like so:

<meta name="csrf-token" content="{{ csrf_token()}}">

I'm assuming you'll be using the logout in your navbar .vue file

like image 93
StoeV_No1 Avatar answered Oct 13 '22 01:10

StoeV_No1


Never used Laravel myself, but you should be able to handle logouts client side without needing to do anything in your backend. At the moment you remove auth token from local storage, so the user loses access to data that requires you to be logged in to get.

You probably call your getUser when you refresh the page and that's why you are only logged out then - you send empty token to your backend server, it can't find a user that's associated to it and returns an empty/default guest object. What's left to do is clear your user state after removing the token in your logout() function or send a request to your /get-user endpoint.

like image 32
dziraf Avatar answered Oct 12 '22 23:10

dziraf