Showing user data and logout

Step 01: Adding reactive object user inside auth.js composable

import { ref, reactive } from 'vue'
import { useRouter } from "vue-router";

const user = reactive({ 
    name: '',
    email: '',
}) 

Step 02: Adding values to user object after successful login inside auth.js composable

const loginUser = (response) => {
    user.name = response.data.name 
    user.email = response.data.email 

    localStorage.setItem('loggedIn', JSON.stringify(true))
    router.push({ name: 'issues.list' })
}

return { ..., user }

Step 03: Changing routes/api.php like below to add api end point /user for fetching user while logged in

Route::group(['middleware' => 'auth:sanctum'], function() { 
    .....
    Route::get('/user', function (Request $request) { 
        return $request->user();
    });
});

Step 04: Now adding getUser() method in auth.js to call api end point and reassign user using loginUser() method. Also this method can be called on any page later

const getUser = () => {
    axios.get('/api/user')
        .then(response => {
            loginUser(response)
        })
}

return { ..., getUser } 

Step 05: Now in app.js the root component getUser() method will be called at the time of onMounted() with following way inside setup() method 

// at the top 
import { createApp, onMounted  } from 'vue' 
import useAuth from './composables/auth';

// changing createApp() from this 
createApp({}) 
    .use(router)
    .use(VueSweetalert2)
    .mount('#app') 

// to this 
createApp({
    setup() { 
            const { getUser } = useAuth()
            onMounted(getUser)
        } 
    })
    .use(router)
    .use(VueSweetalert2)
    .mount('#app') 

Step 06: Now inside Authenticated.vue layout importing auth composable like below and using it in navigation link like below

<script setup>
...
import useAuth from '../composables/auth';

//inside template in navigation link
.....
<li class="nav-item" >
    <a class="nav-link">Hi, {{ user.name }} <small>({{ user.email }})</small></a>
</li>

Step 07: Now before logout button being placed in navigation link, implementing backend code in AuthenticateController.php

// at the top 
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Response;

// adding destroy method 
public function destroy(Request $request): RedirectResponse|Response {
    Auth::guard('web')->logout();

    $request->session()->invalidate();

    $request->session()->regenerateToken();

    if ($request->wantsJson()) {
        return response()->noContent();
    }

    return redirect('/');
}

In code above, instead of redirecting, we are returning a response with no content.

Step 08: Now changing routes/web.php with routes for destroy method

....
Route::post('logout', [\App\Http\Controllers\Auth\AuthenticateController::class, 'destroy']); 
.....

Step 09: Now going back to frontend adding logout() method in auth.js composable

// at the top 
import { ref, reactive, inject } from 'vue'

export default function useAuth() {
    const processing = ref(false)
    ...
    const swal = inject('$swal')
    
    .....
    const logout = async () => { 
        if (processing.value) return
 
        processing.value = true
 
        axios.post('/logout')
            .then(response =>{ 
                localStorage.setItem('loggedIn', JSON.stringify(false));
                router.push({ name: 'Login' })
            })
            .catch(error => {
                swal({
                    icon: 'error',
                    title: error.response.status,
                    text: error.response.statusText
                })
            })
            .finally(() => {
                processing.value = false
            })
    }
    return { ....., logout }

Code above, uses processing variable to process the logut request with axios. After successful logout the storage item LoggedIn value will be false and page will be redirected to login page. If not processing will be false again. We also added swal object of sweetalert to show error message if error occures while processing. To work swal properly we have injected swal variable in the top of useAuth() method. Lastly, we are returning logout() method to component to use it with logout button in Authenticated layout.

Step 10: Creating Logout button in nav links inside Authenticated.vue layout using that logout() method with processing variable

// importing logout() method and processing variable from auth composable 
<script setup>
....
import useAuth from '../composables/auth';

const { user, processing, logout } = useAuth()

// creating logout button in nav links 
......
<li class="nav-item">
    <button @click="logout" :disabled="processing" type="submit" class="btn btn-primary cursor-not-allowed">
        <div v-show="processing" class="float-start spinner-border"></div>
        <span v-if="processing"></span>
        <span v-else>Logout</span>                                    
    </button>
</li> 

So, after all these steps now after refreshing the page, logout button will be there at the top right navigation along with user name with email.
After clicking that logout button, logging out of the site will be done successfully and login page will be redirected to.

Related Posts


Seeding users and role_user data

Seeding clients and issues data

Adding client column in table

Storing issue in db table

Update issue

Permission securing backend

Permission securing frontend