Protecting the routes of both on the front-end and back-end

Step 01: Protecting backend api in routes/api.php calls with laravel sanctum which is installed by default in laravel

Route::group(['middleware' => 'auth:sanctum'], function() { 
    Route::apiResource('issues', App\Http\Controllers\Api\IssueController::class );
    Route::get('clients', [App\Http\Controllers\Api\ClientController::class, 'index']); 
}); 

Step 02: intercepting response and redirecting to login page in case of unauthorized and session expired error inside resources/js/bootstrap.js

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
window.axios.interceptors.response.use(
    response => response,
    error => {
        if (error.response?.status === 401 || error.response?.status === 419) {
            if (JSON.parse(localStorage.getItem('loggedIn'))) {
                localStorage.setItem('loggedIn', false)
                location.assign('/login')
            }
        }
 
        return Promise.reject(error)
    }
)

Step 03: now uncommenting EnsureFrontendRequestsAreStateful middleware inside app/Http/Kernal.php (for laravel 9 and 10)

'api' => [
    \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
    ......
],

For Laravel 11 onwards this sanctun middleware registration needs to be setup inside bootstrap/app.php like below 

......
    ->withMiddleware(function (Middleware $middleware) {
        //
        $middleware->api(append: [
            \Laravel\Sanctum\Http\Middleware\EnsureFrontendRequestsAreStateful::class,
        ]);        
    })
......

Step 04: Now inside config/cors.php changing supports_credentials to true with additional configurations

<?php
return [

    /*
    |--------------------------------------------------------------------------
    | Cross-Origin Resource Sharing (CORS) Configuration
    |--------------------------------------------------------------------------
    |
    | Here you may configure your settings for cross-origin resource sharing
    | or "CORS". This determines what cross-origin operations may execute
    | in web browsers. You are free to adjust these settings as needed.
    |
    | To learn more: https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS
    |
    */

    'paths' => ['api/*', 'sanctum/csrf-cookie'],

    'allowed_methods' => ['*'],

    'allowed_origins' => ['*'],

    'allowed_origins_patterns' => [],

    'allowed_headers' => ['*'],

    'exposed_headers' => [],

    'max_age' => 0,

    'supports_credentials' => true,

];

Step 05: Now adding another header withCredentials for the Axios inside resources/js/bootstrap.js

window.axios.defaults.headers.common['X-Requested-With'] = 'XMLHttpRequest';
window.axios.defaults.withCredentials = true  // withCredentials to true
window.axios.interceptors.response.use(
    response => response,
    error => {
        if (error.response?.status === 401 || error.response?.status === 419) {
            if (JSON.parse(localStorage.getItem('loggedIn'))) {
                localStorage.setItem('loggedIn', false)
                location.assign('/login')
            }
        }
 
        return Promise.reject(error)
    }
)

Step 06: We need to make sure in env file correct APP_URL is in place. If it is set as localhost then sanctum will not work. Hence, virtual host for the project is needed to be created. For this tutorial it is set as http://vue3tracker. So, in our env file it will be like below

APP_URL=http://vue3tracker

In case if sanctum still does not work then laravel route caching needs to be cleared with following artisan commands.

php artisan route:clear

Step 07: In order to protect vue route we are now adding authCheck() method and using it inside beforeEnter property in index.js inside resources/js/routes folder

function authCheck(to, from, next) {
    if (JSON.parse(localStorage.getItem('loggedIn'))) {
        next()
    }
 
    next('/login')
}

const routes = [
    { 
......

// Now adding authCheck() method for the authenticated routes with beforeEnter parameter 
{
    component : AuthenticatedLayout, 
    beforeEnter : authCheck,
    children : [
        {
            path : '/issues', 
            name : 'issues.list', 
            component : IssuesIndex,
            meta: { title:  'Issues List' }
        }, 
        {
            path : '/create-issues', 
            name : 'issues.create', 
            component : IssuesCreate,
            meta: { title:  'Issues Create' }
        }, 
        {
            path : '/edit-issue/:id', 
            name : 'issues.edit', 
            component : IssuesEdit,
            meta: { title:  'Issues Edit' }
        },                          
    ]            
}

Step 08: Lastly, redirecting to login page when root url is access / adding path and redirect property inside guest layout

{ 
    path: '/', // path property added
    redirect: { name: 'login' }, // redirect property added
    component : GuestLayout, 
    children : [
        {
            path : '/login', 
            name : 'Login', 
            component : Login, 
            meta: { title:  'Login' }
        }
    ]        
},

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

Showing user data and logout

Permission securing backend

Permission securing frontend