67

What is the best way to handle expired tokens in laravel 5.

I mean I have a page and it has some links which perform ajax requests. They work fine when the page is loaded but when I wait for sometime then I get a TOKEN MISMATCH error.

Now, I have to refresh the page to make it work again. BUT, I don't want to refresh the page. I want some way to refresh the token or some other work around to make it fix.

I hope you got my point.

Moppo
  • 18,797
  • 5
  • 65
  • 64
Jamal Abdul Nasir
  • 2,557
  • 5
  • 28
  • 47

13 Answers13

43

I think the answer by @UX Labs is misleading. And then the comment from @jfadich seems completely incorrect.

For Laravel 5.4 in May 2017, I solved the problem this way:

Here Is an Answer That Works

In web.php:

Route::post('keep-token-alive', function() {
    return 'Token must have been valid, and the session expiration has been extended.'; //https://stackoverflow.com/q/31449434/470749
});

In javascript in your view:

$(document).ready(function () {

    setInterval(keepTokenAlive, 1000 * 60 * 15); // every 15 mins

    function keepTokenAlive() {
        $.ajax({
            url: '/keep-token-alive', //https://stackoverflow.com/q/31449434/470749
            method: 'post',
            headers: {
                'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
            }
        }).then(function (result) {
            console.log(new Date() + ' ' + result + ' ' + $('meta[name="csrf-token"]').attr('content'));
        });
    }

});

Note that you must not list 'keep-token-alive' in the exclusions within VerifyCsrfToken.php. As @ITDesigns.eu implied in a comment, it's important for this route to verify that there is a valid token currently and that it just needs to have its expiration extended.

Why this approach solves my problem

My Laravel site allows users to watch a video (an hour long), and it uses ajax to post their progress every minute.

But many users load the page and then don't start the video until many hours later.

I don't know why they leave their browser tab open so long before watching, but they do.

And then I'd get a ton of TokenMismatch exceptions in my logs (and would miss out on the data of their progress).

In session.php, I changed 'lifetime' from 120 to 360 minutes, but that still wasn't enough. And I didn't want to make it longer than 6 hours. So I needed to enable this one page to frequently extend the session via ajax.

How you can test it and get a sense for how the tokens work:

In web.php:

Route::post('refresh-csrf', function() {//Note: as I mentioned in my answer, I think this approach from @UX Labs does not make sense, but I first wanted to design a test view that used buttons to ping different URLs to understand how tokens work. The "return csrf_token();" does not even seem to get used.
    return csrf_token();
});
Route::post('test-csrf', function() {
    return 'Token must have been valid.';
});

In javascript in your view:

<button id="tryPost">Try posting to db</button>
<button id="getNewToken">Get new token</button>

(function () {
    var $ = require("jquery");

    $(document).ready(function () {
        $('body').prepend('<div>' + new Date() + ' Current token is: ' + $('meta[name="csrf-token"]').attr('content') + '</div>');
        $('#getNewToken').click(function () {
            $.ajax({
                url: '/refresh-csrf',
                method: 'post',
                headers: {
                    'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                }
            }).then(function (d) {
                $('meta[name="csrf-token"]').attr('content', d);
                $('body').prepend('<div>' + new Date() + ' Refreshed token is: ' + $('meta[name="csrf-token"]').attr('content') + '</div>');
            });
        });
        $('#tryPost').click(function () {
            $.ajax({
                url: '/test-csrf',
                method: 'post',
                headers: {
                    'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
                }
            }).then(function (d) {
                $('body').prepend('<div>' + new Date() + ' Result of test: ' + d + '</div>');
            });
        });


    });
})();

In session.php, temporarily change 'lifetime' to something very short for testing purposes.

Then play around.

This is how I learned how the Laravel token works and how we really just need to successfully POST to a CSRF-protected route frequently so that the token continues to be valid.

Alan Reed
  • 470
  • 4
  • 11
Ryan
  • 22,332
  • 31
  • 176
  • 357
  • 1
    This should have gotten an up vote a while ago. The token and session timeouts are related but not the same. You can have a valid session kept alive by something like laravel-caffeine, but still have the form's csrf_token expire. This help me see the light. – JungleGenius Jul 04 '17 at 17:07
  • 1
    Please note that my comment on the other answer is indeed correct, but does not apply to your answer as written. The key difference is that you **POST** to a route, with a CSRF token, where the other answer uses a **GET** request without the CSRF protection. – jfadich Aug 09 '17 at 21:39
  • 4
    Very simple, thank you! It's even easier with axios, as it automatically sends the latest `XSRF-TOKEN` with every request. You can just do: `setInterval(() => axios.post('/keep-token-alive'), 1000 * 60 * 15);` – Clayton Apr 04 '18 at 01:48
  • 2
    This won't work if the user device goes to sleep for the duration of your session, because while the user sleeps, `setInvall` goes to sleep too: https://stackoverflow.com/a/6347336/2311074 – Adam Nov 05 '19 at 11:38
  • Also there is no need to make the `keep-token-alive` a post nor a CSRF protected route. – Adam Nov 07 '19 at 09:48
  • @Adam I would think in most cases I'd want that route to be auth-protected, CSRF-protected, and a post. But maybe you can explain cases where you wouldn't. And I'm not sure I understand your scenario about a device going to sleep. Are you saying you want the browser to force devices to stay awake? What if the user forcefully sleeps or powers down the device? How would you want your website to behave then? – Ryan Nov 07 '19 at 13:31
  • @Ryan thanks for your answer! Your solution boils down to keep the session alive (by making an ajax call). Why should that mockup-route that just returns a string be an auth-CSRF-protected post request? It only keeps the session of the user alive, so if another malicious server calls the route, it won't be risky, because it has no effect on the session from the infected client. – Adam Nov 07 '19 at 14:12
  • @Ryan I do not want the browser to stay awake. But one scenario where CSRF token becomes invalid, is if the users leaves his PC,the PC goes to sleep (could happen after 1 minute, depending on users settings), then user returns a couple of hours back to his pc. In such a scenario, your script would not keep the session alive and the CSRF token would become invalid. All I am saying is, that using JS to keep the session alive does not always work. Instead I would recommend to increase the lifetime of the session duration, see my answer: https://stackoverflow.com/a/58746758/2311074 – Adam Nov 07 '19 at 14:12
  • I know this answer is a little old, but I keep getting 500 errors showing up in my logs to the URL. For example: `method=POST path="/keep-token-alive" host=www.foo.com request_id=f7176f45-b465-40c3-a77e-d5fe9b08c361 fwd="2601:240:4101:5a70:6da3:3a7d:c39b:e702,162.158.78.177" dyno=web.3 connect=59ms service=345ms status=500 bytes=24140 protocol=https`. I've tested it in my browser and it correctly loads after 15 minutes as expected with a `200` code. Perhaps this happens if someone closes their browser? I can't figure out what's causing the `500` status – BrandonO Aug 16 '20 at 22:49
  • Why do you think that UX Labs answer is misleading? I don't the a problem of returning the csrf token. Its kept in the session of the client. – Adam Mar 15 '21 at 06:33
34

Update 2022; the csrf_token() method will never create a new token, and it simply loads existing CSRF-token from current-session (if any, and returns it).

But this tricks you into thinking it works, because Laravel increases the life-time of the existing CSRF-token, and that each time a request to a CSRF-protected route is made.

For an implemention that really creates new CSRF-token, see:

stackoverflow.com/Get new CSRF token with Ajax?

Original Answer (From 2015)

A work around for it, is to actually get the new token every certain time, otherwise you are defeating the purpose of the csrf token:

<html>
    <head>
        <meta name="csrf_token" content="{{ csrf_token() }}">
    </head>
    <body>
        <script type="text/javascript">
            var csrfToken = $('[name="csrf_token"]').attr('content');
            
            setInterval(refreshToken, 3600000); // 1 hour 
            
            function refreshToken(){
                $.get('refresh-csrf').done(function(data){
                    csrfToken = data; // the new token
                });
            }

            setInterval(refreshToken, 3600000); // 1 hour 

        </script>
    </body>
</html>

In laravel routes

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

I apologize in case of any syntax errors, haven't used jquery for long time, but i guess you get the idea

Top-Master
  • 7,611
  • 5
  • 39
  • 71
UX Labs
  • 1,481
  • 14
  • 29
  • 51
    This as written defeats the point of the csrf_token. You should pass the current token and only return a new token if the old is valid. Otherwise a malicious person could just hit the refresh-csrf route to get a token and use it to make any request that would normally be protected. – jfadich Sep 23 '15 at 20:41
  • 29
    Am I missing something here @jfadich and comment upvoters? Just being able to make a request to the csrf endpoint doesn't give the attacker a way to defeat the csrf protection. The attacker would still need to get the token into the user's session somehow (for example using a SOP bug or a XSS vulnerability) so I have no idea what the above comment means. – PeeHaa Dec 05 '16 at 08:37
  • 2
    This solution is viable, epscially for those of us who uses `$.ajaxSetup({ headers: {'X-CSRF-TOKEN': csrfToken} });` However, you should also `$("input[name=_token]").val(data);` – Vitalij Dec 14 '16 at 06:42
  • 2
    @jfadich, could you elaborate on to how a "malicious person" could hit auth protected "refresh-csrf route"? Please, share your wisdom! – Vitalij Dec 14 '16 at 06:50
  • @ITDesigns.eu, i'm not jfadich, but i think i can answer you question. If "refresh-csrf route" protected with stantard cookie-based authentification, browser will automatically supply cookies for any request to target domain, and attacker can acquire cookies just by executing same ajax request with absolute url: ```function refreshToken(){ $.get(rootUrl + '/refresh-csrf').done(function(data){ csrfToken = data; // the new token }); }``` Protection against such attacks is the purpose of csrf tokens. – berrunder Jan 09 '17 at 16:52
  • 2
    @berrunder, when I said "auth protected", I DID meant auth protected. Your request to auth-protected route will fall before any csrf could get added to anything. Refreshing of csrf is used to not send your input to expired void, in case the user is still active. – Vitalij Jan 09 '17 at 17:11
  • 1
    Please read https://stackoverflow.com/questions/5207160/what-is-a-csrf-token-what-is-its-importance-and-how-does-it-work before vote @jfadich comment. This answer is viable when we only refresh with logged user and a valid token. – Jared Chu Aug 08 '17 at 03:39
  • 2
    @JaredChu Using the example from that answer `cute-cat-pictures.org` can make a request to `mybank.com/refresh-csrf` to get a valid token. Just like that answer said your browser will send the appropriate cookies for `mybank.com` so the attacker will get a valid token. They could then use that token to make a request to `http://www.mybank.com/transfer?to=123456;amount=10000`. – jfadich Aug 09 '17 at 19:50
  • I agree that the answer above lack the security. – Jared Chu Aug 10 '17 at 01:56
  • According to the OWASP page on CSRF, "the attacker has no way to see the response to the forged request". https://www.owasp.org/index.php/Cross-Site_Request_Forgery_(CSRF) – programmerKev Oct 04 '19 at 16:55
  • @jfadich your comment was about 3 years ago, so I believe it may be valid then. But the current situation of things in Laravel is that what you explained refers to the `XSRF-TOKEN` cookie sent to the browser by Laravel, not the [csrf token](https://github.com/jimrubenstein/laravel-framework/blob/f7ba54c132319631163ac0c98101da0a3b16c3ca/src/Illuminate/Foundation/Http/Middleware/VerifyCsrfToken.php#L136) present in either `$request->input('_token')` or `$request->header('X-CSRF-TOKEN')` which Laravel uses to protect the route – Damilola Olowookere Dec 27 '20 at 11:11
26

I combine 2 things for this case:

1. Increase session lifetime

//In config/session.php replace this:

'lifetime' => 120

//with:

'lifetime' => 360

Laravel 5 default lifetime is 120 (minutes), you can change it to whatever value you like, for example 360 (6 hours)

2. Catch the exception and display an error message

//In app/Exceptions/Handler.php replace this:

public function render($request, Exception $e)
{
    if ($e instanceof ModelNotFoundException) {
        $e = new NotFoundHttpException($e->getMessage(), $e);
    }

    return parent::render($request, $e);
}

//with:

public function render($request, Exception $e)
{
    if ($e instanceof ModelNotFoundException) {
        $e = new NotFoundHttpException($e->getMessage(), $e);
    }

    if ($e instanceof \Illuminate\Session\TokenMismatchException) {            
        return redirect('/')->withErrors(['token_error' => 'Sorry, your session seems to have expired. Please try again.']);
    }

    return parent::render($request, $e);
}

So basicaly you redirect the user to the root "/" (you can change this to any path you want) with an error message and on that page you have to do this to display the error message:

@if ($errors->has('token_error'))
    {{ $errors->first('token_error') }}
@endif
paulalexandru
  • 9,218
  • 7
  • 66
  • 94
  • 1
    I'm trying really hard to go through this solution, as I find it very elegant: No token = no session, so redirect flashing the error. The problem is the error is put at the session but it is renewed as redirection creates another one, so at the moment of printing the error it is gone. I'm really stuck here, for 2 days. – Xavi Dec 28 '15 at 15:37
  • @Xavi - I don't know exactly what you have thare, but in case you use a redirect try to add the session error message as a parameter so you can have it on the new page. – paulalexandru Dec 28 '15 at 22:49
  • 1
    what if you redirect to login page with the error on token missmatch error? is it a good approach?? – Jamal Abdul Nasir Jan 26 '16 at 12:00
  • 2
    So you are redirecting a user to homepage with "Haha, you are too late, slowpoke" message, when token is expired? That's "convenient" :) Imagine user satisfaction after composing an articles for several hours and getting that "useful" message while loosing all his/her work. – Vitalij Dec 14 '16 at 06:31
  • 1
    @ITDesigns.eu - We've all been through this kind of situation and is frustrating, but in the same time we can't blame an application when we leave it open for 2 weeks and after that we want to continue from the same spot. It's not possible ! What do you want to do instead of showing a message? Do an ajax call every 1 minute and let the user know when his session expired? I don't think that this is the way. So a decent way is to increase the session time and in the same time disaply an error message. It's not your fault that the user session expired, it's his. – paulalexandru Dec 14 '16 at 07:13
15

According to the docs:

Laravel automatically generates a CSRF "token" for each active user session managed by the application.

This means, for any individual the csrf code is the same for any page that the user visits. It becomes invalid once your session expires. Thus if you set the lifetime to 1 week, CSRF token will only expire after 1 week.

This can achieved like this in config/session.php:

 /*
    |--------------------------------------------------------------------------
    | Session Lifetime
    |--------------------------------------------------------------------------
    |
    | Here you may specify the number of minutes that you wish the session
    | to be allowed to remain idle before it expires. If you want them
    | to immediately expire on the browser closing, set that option.
    |
    */

    'lifetime' => 60 * 24 * 7, // Set session lifetime to 1 week

    'expire_on_close' => true,

Why I dont like any of the above answers:

  1. Answer from UX Labs:

Keeps the session forever alive and recreates a new CSRF token after a fixed time. This is an issue if the user has multiple taps open. Everytime one tap refreshes the CSRF token, all the other tabs become invalid.

  1. Answer from Ryan

This answer is better, because it does not change the CSRF token, so multiple tabs are not effected. It simply keeps the session alive with making a js call after a fixed time with setInterval. However, setInterval does not work while the PC goes to sleep. So the session may expire when the PC goes to sleep, which is also a likly scenario. Therefore, instead of trying to keep the session alive by js-calls,just increase lifetime.

  1. Answer from paulalexandru

Displaying an error when session is timed out is okay, but it would be better if the issue never happens. Setting lifetime to 6h is not enough, because its likly that a tab may be open for a couple of days.

  1. Other answers

All the other answers propose to disable CSRF for the route in questions, but this is of course no option, because it creates a big security risk.

Adam
  • 25,960
  • 22
  • 158
  • 247
  • 1
    Wouldn't this create a huge database table / list of files (depending on which you use to save sessions) with possibly up to 50 years worth of sessions? – user125661 May 12 '20 at 23:22
  • @user125661 yes it does. I actually had issues with that so I changed the session lifetime to a week and used `redis`. Adjusted the answer. – Adam May 13 '20 at 07:28
  • 1
    Alright! You still mention "50 years" in reason 2 why you don't like the other answers. – user125661 May 13 '20 at 15:37
  • @user125661 thanks I adjusted it. But in the end, it probably just depends on how large your traffic is, how much capacity you have for your sessions. A good solution is a time that is long enough to avoid session timeout but avoid overflow on the server. – Adam May 13 '20 at 15:46
  • Yeah. I just posted a solution below which doesn't require you to extend the session lifetime, works with multiple tabs open, and works in case the session expired. – user125661 May 13 '20 at 16:04
3

Best way to handle this Exception is with App\Exceptions\Handler.php.

public function render($request, Exception $e) {

        if ($e instanceof \Illuminate\Session\TokenMismatchException) {            
            return Redirect::back()->withErrors(['session' => 'Désolé, votre session semble avoir expiré. Veuillez réessayer.']);
        }

        return parent::render($request, $e);
    }


and where ever you wanna show this message (in all your pages that contains csrf_token), add this piece:

<div>
@if(count($errors)>0)
    @foreach($errors->all() as $error)
        <ul>
            <li>{{$error}}</li>
        </ul>
    @endforeach
@endif
</div>

Siempay
  • 876
  • 1
  • 11
  • 32
2

Increase the lifetime of your sessions. You can do so by editing the config/session.php file in your laravel configuration.

/*
|--------------------------------------------------------------------------
| Session Lifetime
|--------------------------------------------------------------------------
|
| Here you may specify the number of minutes that you wish the session
| to be allowed to remain idle before it expires. If you want them
| to immediately expire on the browser closing, set that option.
|
*/

'lifetime' => 120,
Thomas Venturini
  • 3,500
  • 4
  • 34
  • 43
  • 5
    yes, u r right. but wt if dat time is passed and the token is expired. – Jamal Abdul Nasir Jul 16 '15 at 10:59
  • ok, but if you are expecting to use a session longer than two hours, then you should set the value according to the expected time range. means, if your user should be able to use his session again after two hours or eaven a week, than thats the setting you should use. any other solution isn't a clean way - at least in my opinion ^^ – Thomas Venturini Jul 16 '15 at 12:28
  • 1
    But sometimes the user is not logged in and the token mismatched error is thrown. I dont understand why this happens. – Jamal Abdul Nasir Nov 18 '15 at 08:10
  • some weeks ago I had to deal with such a problem again. Use an ajax request to get a new token before any other ajax call is made. No clean approach but since we had to deal with some problems, this way was (in my particular case) the best way to go. take a look at this answer: http://stackoverflow.com/questions/31449434/handling-expired-token-in-laravel/31451983?noredirect=1#answer-31451123 – Thomas Venturini Nov 18 '15 at 12:55
2

I have a simple solution that:

  • Doesn't require you to extend the session lifetime.
  • Works with multiple tabs open.
  • Also works if the session did time out because the device was turned off.

in /routes/web.php:

$router->get('csrf-token', function() {
   return request()->session()->token();
});

This simply returns the current csrf token.

  • In case the token is invalid by the time this route gets called (for example when the device was turned off for a long time), it will return a new token, which was created by starting the session.
  • In case there still is a valid token, it will be returned. Since calling this route will extend the session, the token lifetime is extended as well.

Because this only returns a new token when necessary, there are no problems when having multiple tabs open as described by @Adam.

You just need to make sure to call the above route every X minutes (where X is your session lifetime - 5 minutes), and update any _token inputs. I do this as follows (i use momentjs and axios here):

handleNewCsrfToken();

// Use visbility API to make sure the token gets updated in time, even when the device went to sleep.
document.addEventListener('visibilitychange', function() {
    if (document.visibilityState === 'visible') {
        setTimeoutToRefreshCsrfToken();
    } else if (document.visibilityState === 'hidden') {
        clearTimeout(refreshCsrfTokenTimeout);
    }
});

function handleNewCsrfToken() {
    updateCsrfTokenTimeoutTarget();
    setTimeoutToRefreshCsrfToken();
}

function updateCsrfTokenTimeoutTarget() {
    csrfTokenTimeoutTarget = moment().add(2, 'hour').subtract(5, 'minute');
}

function setTimeoutToRefreshCsrfToken() {
    refreshCsrfTokenTimeout = setTimeout(refreshCsrfToken, csrfTokenTimeoutTarget.diff());
}

function refreshCsrfToken() {
    axios.get('/csrf-token').then(function(response) {
        document.getElementsByName('_token').forEach(function(element) {
            element.value = response.data;

            handleNewCsrfToken();
        });
    });
}
user125661
  • 1,558
  • 12
  • 28
  • This seems to be the most modern approach on the server side. You can probably replace `return request()->session()->token();` by `return csrf_token();` because the helper does the same. – meduz' Aug 30 '20 at 23:29
  • I believe your solution is identical to https://stackoverflow.com/a/31451123/2311074 right? Also I may have been wrong about the multiple tabs issue. – Adam Mar 15 '21 at 06:29
  • This defeats the purpose of CSRF token, as anyone could make a request to your new URI prior of making a POST request to your CSRF protected form. – Binar Web Apr 23 '21 at 08:14
  • @BinarWeb anyone requesting the CSRF will get one specifically bound to his own session. So I don't see how that would defeat the purpose of CSRF tokens. – user125661 Apr 24 '21 at 14:46
  • To be safe you must have POST method accepted in the backend, instead of GET. And must ask for a new token, providing the actual one. This solution is a good idea, but the problem is that if the computer is switched off (or tab changed) for more than 2 hours, the setTimeout will work to request the backend route atm the tab is active again to get the new CSRF token, which will not work if it accepts POST method as the current CSRF will already be expired. And the backend route will response with 419 error. – Henrikh Jan 03 '22 at 21:28
  • @Henrikh could you explain why you think it should be POST instead of GET please? – user125661 Jan 04 '22 at 22:18
  • As I dig deeper, seems I'm wrong about the request method being POST. Should I delete my comment? Thought of an extra layer of security, but seems it doesn't protect from anything. Researching made me think it should, but logically, I still don't see a valid reason. If anyone sees, please comment. Thanks, @user125661 for the solution. – Henrikh Jan 05 '22 at 23:14
2

try this in your main layout file

@guest
    <meta http-equiv="Cache-Control" content="no-cache, no-store, must-revalidate" />
    <meta http-equiv="Pragma" content="no-cache" />
    <meta http-equiv="Expires" content="0" />
    <meta http-equiv="refresh" content="{{config('session.lifetime') * 60}}">
@endguest
Jean Freitas
  • 209
  • 1
  • 5
  • 2
    This will refresh your page unintentionally which is not something you would want if you are working with it. – tomvo May 18 '21 at 06:50
1

a short and fast way.... for handling ajax requests,when token expire : add this script to the end of master layout or your document

$(window).load(function(){
    $.ajaxSetup({
        statusCode: {
            419: function(){
                    location.reload(); 
                }
        }
    });
});

and for handling http requests when token expires, create 419.blade.php in this path: \resources\views\errors and add this script to it:

<script type="text/javascript">
    //reload on current page
    window.location = '';

</script>
fatemeh sadeghi
  • 1,757
  • 1
  • 11
  • 14
0

Circum-navigating the token is generally accepted as a terrible approach but there are problems with using js timers mentioned above too. js seetTimeout/setInterval is unreliable when the browser tab is either not it focus, minimised or in the case of many users, thier laptop/device is sleeping/closed etc.

A better route might be to use a js timer to recalculate the 'time to die' from a datestamp set in a cookie (or meta tag for fussy GDPR no-cookie users). this datestamp will be the realworld (timezoned) time the session will die and is updated every page refresh. This way, it doesn't matter what the browser/device was doing/not doing whilst you were away AND it'll still be acurate for those with 'keep me signed in' etc.

The next problem is what to do instead of auto resfreshing the token - present the user with a 're-login in' form (modal/popup) that ajaxes the new token to the page as mentioned above.

pSouper
  • 11
  • 1
  • Not sure why this was downvoted. Timers in browsers are terrible timekeepers. We use setInterval() to check the current server timestamp to match against the session cookie expiration before showing a warning modal that the user session is about to time out. The same should be used to refresh the CSRF token. – WebTigers Sep 09 '20 at 10:29
0

You may try Caffeine for Laravel package it set an interval then it refresh the token like suggested in some answers also it will be added automatically in every form having csrf token

Aref Ben Lazrek
  • 1,056
  • 1
  • 11
  • 19
-2

I think the best option is to take the lifetime configuration of the config/session.php file, then the lifetime value multiplied by 60 * 1000 in the javascript code. Use helper function config() provided by laravel, it might look like this:

<script type="text/javascript">
    var timeout = ({{config('session.lifetime')}} * 60) * 1000;
    setTimeout(function() {
        //reload on current page
        window.location = '';
    }, timeout);
</script>
  • 1
    Let's say a user wrote an hour long article on your website form and he hits the submit button after his laptop comes out of stand-by. poof goes the article. – Binar Web Apr 23 '21 at 08:27
  • I forgot to mention that `setTimeout` are [terrible when tab is out of focus](https://stackoverflow.com/a/51854308/9618184). – Binar Web Apr 23 '21 at 08:33
-3

This are all workarounds that I dont like.. (but I admit they can work) I dont know since witch version this exists on Laravel, but there is a way to exclude pages from CSRF token validation:

https://laravel.com/docs/5.5/csrf

Simply adding a record on $except array on VerifyCsrfToken Middleware with your uri that you want to exclude. Please take in account, this must only be done on specific cases.

This is the best solution for me... Simple and just like (almost) everything on Laravel, they already thought about it. ;)

crisleiria
  • 51
  • 1
  • 7
  • 2
    It seems like you might not understand https://en.wikipedia.org/wiki/Cross-site_request_forgery You didn't explain the risks of disabling that protection and why that's an acceptable trade-off in your scenario. – Ryan Jan 27 '20 at 00:45