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' } } ] },