Framework: Laravel 5.5 - The page has expired due to inactivity in Google Chrome

Created on 19 Feb 2018  路  36Comments  路  Source: laravel/framework

I have a form which includes {{ csrf_field() }}

When I submit the form in Firefox (v57.0.4) it works fine no issues.

When I submit the same form in Chrome (v63.0.3239.132) i keep getting:

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

I've tried to clear cookies/browser cache and it makes no difference. The issue is related to Chrome only as everything works fine in other browsers such as Firefox and Edge.

In my env file I have the following set:

SESSION_DRIVER=file

What I have noticed is that when I submit the form in Chrome, a new session file seems to be generated each time inside storage\framework\sessions. In fact every time I refresh the page or go to another page a new session file is being generated?

Another thing I've noticed is that if I login to my application in Chrome without selecting the remember me checkbox everything works fine. But if I login with the remember me checkbox selected, I get the above behavior. So the issue is something to do with how the remember me token is stored perhaps?

Note I'm running application on localhost using wamp on windows 10. This issue is only happening in Google Chrome.

Anyone got any tips to fix?

Most helpful comment

For my part I get the same problem.
In my case I had

public function index() { Session::flush(); return view('home'); }

getting rid off my Session resolve my problem.

All 36 comments

I havent heard of this before. Sounds like something in your project.

5.2 is not supported anymore. Try upgrading to 5.5 or 5.6, there have been lots of bug fixes since then

Updated to 5.5 (fresh install) and I get same issue - instead of token mismatch error message i get The page has expired due to inactivity. Please refresh and try again. displayed which I'm assuming is trying to tell me the same thing.

All other behavior is identical i.e. generating new session file on each page load/refresh but everything works fine when login in without checking the remember me checkbox.

It's only happening in Chrome by the way.

Scoured a dozen forums and no one has yet supplied a clear solution to the issue.

I've never heard of this before.

Have you tried on another computer? Sounds like Chrome is not allowing sessions on your domain, and so each page load causes a new session to be enabled. It's likely a config issue with Chrome.

Why does it work though when i sign in without selecting the remember me checkbox. The issue is being caused when I sign in by selecting the remember me checkbox and only in Chrome?

Check your session.php to see if you have anything set like this is true and you're accessing via HTTP or something.

'secure' => env('SESSION_SECURE_COOKIE', false),

I access the site as: localhost:8000/

This is what I have in session.php:

'driver' => env('SESSION_DRIVER', 'file'),
'lifetime' => env('SESSION_LIFETIME', 120),
'expire_on_close' => false,
'encrypt' => false,
'files' => storage_path('framework/sessions'),
'connection' => null,
'table' => 'sessions',
'store' => null,
'lottery' => [2, 100],
'cookie' => env(
    'SESSION_COOKIE',
    str_slug(env('APP_NAME', 'laravel'), '_').'_session'
),
'path' => '/',
'domain' => env('SESSION_DOMAIN', null),
'secure' => env('SESSION_SECURE_COOKIE', false),
'http_only' => true,
'same_site' => null,

and this is what I have in env file:

APP_NAME=xyz-xyz
APP_ENV=local
APP_KEY=base64:LhyBmW6dl3E6ZZ+nwClsmVa7ONHfTkl7Sl1vSxY9f44=
APP_DEBUG=true
APP_LOG_LEVEL=debug
APP_URL=http://localhost

DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=xyz
DB_USERNAME=root
DB_PASSWORD=

BROADCAST_DRIVER=log
CACHE_DRIVER=file
SESSION_DRIVER=file
SESSION_LIFETIME=120
QUEUE_DRIVER=sync

REDIS_HOST=127.0.0.1
REDIS_PASSWORD=null
REDIS_PORT=6379

MAIL_DRIVER=smtp
MAIL_HOST=smtp.mailtrap.io
MAIL_PORT=2525
MAIL_USERNAME=
MAIL_PASSWORD=
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=
MAIL_FROM_NAME=

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1

Could we have a glimpse at your views ? As for the authentication, are you using a custom solution ?

This is the login view:

 {!! Form::open(['method' => 'POST', 'url' => 'jobseeker/login']) !!}
    <div class="form-group @if ($errors->login->has('email')) has-error @endif">
        <label for="email" class="">Email address <span class="field-indicator-required">*</span> </label>
        {!! Form::email('email', old('email'), ['class' => 'form-control']) !!}
        @if ($errors->login->has('email')) <p class="help-block">{{ $errors->login->first('email') }}</p> @endif
    </div>

    <div class="form-group @if ($errors->login->has('password')) has-error @endif">
        <label for="password" class="">Password <span class="field-indicator-required">*</span> </label>
        {!! Form::password('password', ['class' => 'form-control']) !!}
        @if ($errors->login->has('password')) <p class="help-block">{{ $errors->login->first('password') }}</p> @endif
    </div>
    <div class="checkbox">
        <label>
            {!! Form::checkbox('remember', 'true', true) !!} Keep me signed in

        </label>
    </div>
    <button type="submit" class="btn btn-primary pull-right">Sign in</button>
    <div class="clearfix"></div>
  {!! Form::close() !!}

This is the login controller where I've overridden some of the out of the box methods

public function login(LoginRequest $request)
{

    if ($this->hasTooManyLoginAttempts($request)) {
        $this->fireLockoutEvent($request);

        return $this->sendLockoutResponse($request);
    }

    if ($this->attemptLogin($request)) {
        return $this->sendLoginResponse($request);
    }

    $this->incrementLoginAttempts($request);

    return $this->sendFailedLoginResponse($request);

}


protected function attemptLogin(Request $request)
{

    $user = User::where('email', '=', $request->input('email'))->first();
    if ($user && $user->hasRole('manager'))
       return $this->guard()->attempt($this->credentials($request), $request->filled('remember'));

    return false;
}


protected function guard()
{
    return Auth::guard('manager');
}

The fact it occurs with google chrome, and not firefox etc - means it is somehow browser related and not due to Laravel, Blade or anything else.

If you can supply a demo website, I'd like to try my chrome and firefox against it to replicate.

You should try with a blank Laravel install and confirm that works for you, then slowly add everything back in until you find the cause.

The reality is no one else is experiencing this issue (otherwise we would have 1000's of reports of issues of Laravel not being comptabile with Google Chrome) - but I'm open to the idea is this a strange edge case somehow...

Also try incognito mode, or disable all addons/extensions.

Check to make sure you do not have another application running with the same APP_NAME value

APP_NAME=xyz-xyz

I had this same problem for over a year when I created subdomains of my companies primary domain. This is the session config for the cookie name, which Chrome is only setting on the primary domain instead of per subdomain

'cookie' => env( 'SESSION_COOKIE', str_slug(env('APP_NAME', 'laravel'), '_').'_session' ),

By updating the app name, it will alter the cookie name and you should not have this problem anymore

Verify that your config/session.php file contains this line

'domain' => env('SESSION_DOMAIN', null),

Then remove the SESSION_DOMAIN line in your .env file

I have the same issue on laravel 5.5

having the same issue here... working fine on heroku dev server, but locally, cookies is empty..

I have the same issue but maybe with different behavior.
I'm using Laravel 5.5.39 on my local windows 10.

The same app is working fine or production, but showing this message only on the local machines.
I've tried it on both my PC and laptop using google chrome, firefox, and Edge and still showing the same message "The page has expired due to inactivity. Please refresh and try again." when I try to log in.

Also, I tried to use firefox on Virtual Machine Ubuntu to connect to my laptop IP address to make sure that there is no Cookie of browser related issue.

Still No Luck 馃憥

I noticed the following:
When I open only the home page, three new files get created in storage/framework/sessions
When I click on login link, four new files get created
If I type in username and password, one new file get created

@nabboly I resolved mine, for mine it works on heroku because I wrote some very specific code to connect to PostgreSQL on heroku without db driver check (heroku / mysql) and the code throw error on my dev environment secretly. Due to I am running via php artisan serve locally, the error is hidden from me. The error is shown after I installed XAMPP and the error was thrown right on the screen, fixed that and everything works perfectly fine!

@rmf0938 I was just having the same problem and changing APP_NAME was the solution. Forgot to change from the default of "Laravel".

Pay attention on php.ini mbstring.func_overload parameter. It has to be set to 0. And mbstring.internal_encoding set to UTF-8. In my case that was a problem.

For my part I get the same problem.
In my case I had

public function index() { Session::flush(); return view('home'); }

getting rid off my Session resolve my problem.

Same error here, but in default login page.
I solved changing PHP options to default (maybe be a wrong settings on MAX_INPUT_TIME or
MAX_INPUT_VARS).

Check if you session.php contain this Line.
'domain' => env('SESSION_DOMAIN', null),

if you are working on localhost or production add SESSION_DOMAIN=YOUR_LOCALHOST_DOMAIN on .env file then as usual php artisan config:cache it will work 馃挴

@Adam-78 - did you resolve this issue?

In my case, I have got the same error message and then figured out that I have missed adding CSRF token for the form field.
With Laravel 5.6 using Blades templates, it's pretty easy

<form method="POST" action="/profile">
    @csrf
    ...
</form>

It doesn't work, then Refresh the browser cache and now it might work

I'm going to close this, as it seems to be a local issue.

If anyone can show its a bug in the framework itself - I'm happy to reopen this.

Hi, I had the same problem but the problem is not in the framework but in the browser. I don't know why but google chrome blocks cookies automatically, in my case. After allowed cookies the problem was resolved.

As far as I understand the problem stems from CSRF token invalidation due to session expiry.

I found a simple solution for handling this error more or less gracefully.

Use the VerifyCsrfToken::handle() in your application to wrap the parent call to handle in a try-catch block which catches the TokenMismatchException and redirects back with an error message.

You can see a simple example here: VerifyCsrfToken

I had a version of PHP 7.1
I installed version PHP 7.2 and the problem was solved

Hi
I'm facing the same problem: I get the error The page has expired due to inactivity. Please refresh and try again. on a Laravel 5.6.39. The browser "Network tab" says error login - 419 unknown status

As soon as I refresh the page, I immediately get the error. So I never see the login view anymore, then I'm stuck. Think to common users that have no experience and only try to refresh the page. If it doesn't work they leave your app.

I can reproduce the error following these steps:

  • go to login view
  • enter username and password and don't check "remember me" flag
  • wait that session expires (for test purpose I set SESSION_LIFETIME to 1 minute)
  • hit Login button and I get that error

I already read and tried the most common causes:

  • @csrf is present in the login form (it's the default authentication by Laravel)
  • the folder storage has 755 but tried also with 775 and 777
  • tried to launch php artisan cache:clear php artisan config:clear php artisan route:clear php artisan view:clear php artisan config:cache php artisan key:generate
  • I'm using the default SESSION_DRIVER=file but in production I also tried to replace it with SESSION_DRIVER=cookie with SESSION_DOMAIN=https://app.my-domain.com/

Here my code (controllers, view, routes, .env, ...) related to this issue:
https://gist.github.com/dangelion/aa7fc54ea75f7b2d6062fc79f07e04e8

I really have no more idea to solve this.
Some helps? Thanks

An expired csrf token causes this. The behavior is expected, it's just how form submissions with csrf, work. However, the message displayed to the end-user is indeed misleading. It's been discussed on the repo many times but has never been changed. If you go to any of Laravel's official sites' login form, and wait for the session to expire, the same thing happens.

You need to, first, make sure you're using csrf with every form, catch the exception, and customize how you handle this. Generally you can just redirect to the login page.

Hi @devcircus
thanks for answer, this clarifies me a lot. So why Laravel devs don't put in that error page a link, for example, to login or to the previous page? Like it is, it's a deadpoint.

Could you advice me a good solution to handle the exception, redirecting the user to the login (maybe with a flash message)?

Thanks

This is indeed something to do with the session domain in Chrome. I've run into this issue of couple of times running laravel 5.5 through Docker with memcached as the cache_driver.

In Chrome:
CACHE_DRIVER=memcached, SESSION_DOMAIN [not set] fails
CACHE_DRIVER=file, SESSION_DOMAIN [not set] succeeds
CACHE_DRIVER=memcached, SESSION_DOMAIN=MY_DOMAIN succeeds

In firefox:
CACHE_DRIVER=file, SESSION_DOMAIN [not set] succeeds
CACHE_DRIVER=memcached, SESSION_DOMAIN [not set] succeeds
CACHE_DRIVER=memcached, SESSION_DOMAIN=MY_DOMAIN succeeds

FTW:
CACHE_DRIVER=memcached, SESSION_DOMAIN=MY_DOMAIN

.... in my case

I was using localhost for this app (1st one live on my computer)

Defining a new host name and updating APP_URL and SESSION_URL followed by php artisan config:cache solved the issue.

If it's related to cookies then, you should do this below.
https://i.imgur.com/z69i7Vb.png

In my case, mysql in vagrant was stopped with error (Can't connect to local MySQL server through socket '/var/run/mysqld/mysqld.sock'). "service mysql restart" was not working. I had look in "sudo cat /var/log/mysql/error.log" and saw: "2235-03-14T13:05:45.511737Z 121 [Warning] Iteration 1: Current time obtained from system is greater than 2038".
Command "date" showed: "Sat Mar 14 13:45:25 UTC 2235". I don't know why it happened. I changed right date and it worked.

As far as I understand the problem stems from CSRF token invalidation due to session expiry.

I found a simple solution for handling this error more or less gracefully.

Use the VerifyCsrfToken::handle() in your application to wrap the parent call to handle in a try-catch block which catches the TokenMismatchException and redirects back with an error message.

You can see a simple example here: VerifyCsrfToken

Thanks a lot this actually solved my problem.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

gabriellimo picture gabriellimo  路  3Comments

PhiloNL picture PhiloNL  路  3Comments

kerbylav picture kerbylav  路  3Comments

Anahkiasen picture Anahkiasen  路  3Comments

felixsanz picture felixsanz  路  3Comments