How to generate new CSRF token with Ajax in Laravel

Laravel protects all post routes form CSRF attack. Laravel automatically generates CSRF token for each active user session. This token verifies when user makes post request. This ensures that the user who is requesting is the authenticated user.

This token is only valid before the token is expired. After that if you make any request, then you get the bellow error in page.

The page has expired due to inactivity. Please refresh and try again.

So in this article, I will show you how to genetate new token with Ajax request in Laravel.

First include the below <meta> tag the <head>.

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

Then in your Ajax request add csrf token value in Header. This is added to check if the current token is valid or expired:

headers: {
    'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}

And in the web.php file, return new csrf token.

Route::post('refresh-csrf', function() {
    return csrf_token();
});

Here is how you can test and get a idea for how the csrf tokens work:

This is  index.blade.php

<!DOCTYPE html>
<html>
<head>
    <meta name="csrf-token" content="{!! csrf_token() !!}" />
</head>
<body>
    <button id="getNewToken">Get new token</button>
    <script src="https://code.jquery.com/jquery-3.5.0.min.js"></script>
    <script type="text/javascript">
        $(document).ready(function () {
            $('body').prepend('<div> Current token is: ' + $('meta[name="csrf-token"]').attr('content') + '</div>');
            $('#getNewToken').click(function () {
                $.ajax({
                    url: '/refresh-token',
                    method: 'get',
                    headers: {
                        'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                    }
                }).then(function (response) {
                    if (response.token != null) {
                        $('meta[name="csrf-token"]').attr('content', response.token);
                        $('body').prepend('<div> New token is: ' + response.token + '</div>');
                    } else {
                        $('body').prepend('<div>' + response.error + '</div>');
                    }
                });
            });
        });
    </script>
</body>
</html>


In web.php:

// load page
Route::get('/', function() {
    return view('index');
});
// refresh token
Route::get('refresh-token', 'HomeController@index');


And this is your HomeController.php file:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class HomeController extends Controller
{
    // ================================================
    /* method : index
    * @param  : 
    * @Description : get refresh token
    */// ==============================================
    public function index(Request $request)
    {        
        if ($request->header('X-CSRF-TOKEN') != csrf_token()) {
            return response()->json(['token' => csrf_token()]);
        } else {
            return response()->json(['error' => 'token is not expired']);
        }
    }
}

In .env file, temporarily change 'SESSION_LIFETIME' to 1 for testing purposes.

This is how the Laravel token works and how we can get new token.