fisharebest / webtrees

Online genealogy
https://webtrees.net
GNU General Public License v3.0
429 stars 294 forks source link

Log out after changing anything #4869

Closed mathiasbockwoldt closed 6 months ago

mathiasbockwoldt commented 11 months ago

Using Webtrees 2.1.7. I have the same problem as was reported before (#4717 and forum discussion linked therein). When I am logged on, I can edit the tree without problems for about 30 minutes. Then, I will be logged out. This can happen while submitting changes, or while a request is send in the background, for example, to fetch suggestions when entering a last name or place. This happens when adding events to people, creating new sources or media objects or any other edit. I have not had the problem while just browsing. When I am logged on and keep the session open for a longer time (e.g. over night), I can do a few edits before being logged out again.

Here are two logs that show the problem with two different patterns (redacted to remove server url).

The first was upon submitting a new person. The POST gets a 404 (!), then I'm sent to login and the request in the background gets a 405. After log in, I am in the main page again, not the page that I was before being logged out.

[20/Aug/2023:21:00:23 +0200]    GET /webtrees/tree/main/media-thumbnail?xref=X3461&fact_id=b7d2684a1e1846aad096349148f84f9b&w=30&h=40&fit=crop&mark=0&s=f2b69ff760cf6a76bee40721e45ffd1e HTTP/1.1   200
[20/Aug/2023:21:00:30 +0200]    POST /webtrees/tree/main/add-child-to-family/F465 HTTP/1.1  404
[20/Aug/2023:21:00:34 +0200]    GET /webtrees/login?url=https---webtrees%2Ftree%2Fmain%2Fadd-child-to-family%2FF465 HTTP/1.1    200
[20/Aug/2023:21:00:43 +0200]    POST /webtrees/login HTTP/1.1   302
[20/Aug/2023:21:00:43 +0200]    GET /webtrees/tree/main/add-child-to-family/F465 HTTP/1.1   405
[20/Aug/2023:21:00:44 +0200]    GET /favicon.ico HTTP/1.1   200
[20/Aug/2023:21:00:51 +0200]    GET /webtrees/ HTTP/1.1 302
[20/Aug/2023:21:00:52 +0200]    GET /webtrees/tree/main/my-page HTTP/1.1    200

In the second example, the log out happened while editing (not submitting). No 404 or 405 here, just multiple requests (for place autocompletion) all kind of being replaced by login.

[22/Aug/2023:11:30:50 +0200]    POST /webtrees/tree/main/add-child-to-family/F80 HTTP/1.1   302
[22/Aug/2023:11:30:51 +0200]    GET /webtrees/tree/main/individual/X3754/Peder-Martin-Pedersen HTTP/1.1 200
[22/Aug/2023:11:30:51 +0200]    GET /webtrees/tree/main/media-thumbnail?xref=X3753&fact_id=e58cbb202f97180d15ef90e918bae65e&w=100&h=100&fit=contain&mark=0&s=0531614190b67cffdbb4a9171bc3e570 HTTP/1.1  200
[22/Aug/2023:11:30:57 +0200]    GET /webtrees/tree/main/add-child-to-family/F80/F?url=https---webtrees%2Ftree%2Fmain%2Findividual%2FX3754%2FPeder-Martin-Pedersen%23tab-relatives HTTP/1.1  200
[22/Aug/2023:11:31:20 +0200]    GET /webtrees/tree/main/autocomplete/place?query=holm HTTP/1.1  302
[22/Aug/2023:11:31:20 +0200]    GET /webtrees/ HTTP/1.1 302
[22/Aug/2023:11:31:20 +0200]    GET /webtrees/login?url= HTTP/1.1   200
[22/Aug/2023:11:31:29 +0200]    GET /webtrees/tree/main/tom-select-source?at=%40&query=18 HTTP/1.1  302
[22/Aug/2023:11:31:29 +0200]    GET /webtrees/ HTTP/1.1 302
[22/Aug/2023:11:31:29 +0200]    GET /webtrees/login?url= HTTP/1.1   200
[22/Aug/2023:11:31:29 +0200]    GET /webtrees/tree/main/tom-select-source?at=%40&query=1864 HTTP/1.1    302
[22/Aug/2023:11:31:29 +0200]    GET /webtrees/ HTTP/1.1 302
[22/Aug/2023:11:31:30 +0200]    GET /webtrees/login?url= HTTP/1.1   200
[22/Aug/2023:11:31:32 +0200]    GET /webtrees/tree/main/create-source HTTP/1.1  302
[22/Aug/2023:11:31:33 +0200]    GET /webtrees/ HTTP/1.1 302
[22/Aug/2023:11:31:33 +0200]    GET /webtrees/login?url= HTTP/1.1   200
[22/Aug/2023:11:31:40 +0200]    GET /webtrees/tree/main/add-child-to-family/F80/F?url=https---webtrees%2Ftree%2Fmain%2Findividual%2FX3754%2FPeder-Martin-Pedersen%23tab-relatives HTTP/1.1  302
[22/Aug/2023:11:31:41 +0200]    GET /webtrees/ HTTP/1.1 302
[22/Aug/2023:11:31:41 +0200]    GET /webtrees/login?url= HTTP/1.1   200
[22/Aug/2023:11:31:45 +0200]    POST /webtrees/login HTTP/1.1   302
[22/Aug/2023:11:31:46 +0200]    GET /webtrees/ HTTP/1.1 302
[22/Aug/2023:11:31:46 +0200]    GET /webtrees/tree/main/my-page HTTP/1.1    200

I don't think I fiddled with any Apache or PHP configs on my server (rented from a commercial actor) more than activating the nicer urls via .htaccess. If it helps, I can share configs of interest.

hartenthaler commented 11 months ago

I have the same problem for several months now.

mathiasbockwoldt commented 11 months ago

The solution in this thread (from today) works for me: https://www.webtrees.net/index.php/en/forum/2-open-discussion/38241-logged-out-automatically

Create a php.ini (or .user.ini (with preceding dot!)) in the root folder of webtrees with the following content.

session.gc_maxlifetime=86400

This will guard the session for 86400 seconds or 1 day. The behaviour of the session garbage collector also fits to my observed behaviour. It was set to 1440 seconds or 24 minutes and then had a 1% chance in each php call to run. So the perceived time between two log outs was about 30 minutes. This also explains why I could do some things after I stayed logged on over night, but only a few times.

However, this does not explain, why webtrees does not update the session as it should whenever I interact with the tool (if I understood the concept correctly). Or did I get this wrong?

Jefferson49 commented 11 months ago

I also have the same problems and it did not improve with 2.1.17.

I also tried to change the above PHP setting (session.gc_maxlifetime=86400). However, after 30 min. I was logged off again. Maybe, it just happened by random or because the session was not reset or newly started. I will continue to watch the behavior.

mathiasbockwoldt commented 11 months ago

You can check if the file is in effect by going to Control panel -> Server information (under Website). Search for session.gc_maxlifetime. You should see your change reflected there.

If the changes did not take effect, check with your hoster, how to change settings and if that is even possible. Depending on configuration, at some hosters you need a "php.ini" file, others need ".user.ini" and even others need php configuration to go into the ".htaccess".

fisharebest commented 11 months ago

@mathiasbockwoldt - go to Control panel -> Server information and scroll down to the section Session.

Can you post the information here.

mathiasbockwoldt commented 11 months ago
Directive              Local Value Master Value
session.gc_divisor             100          100
session.gc_maxlifetime       86400         1440
session.gc_probability           1            1

For me, creating a .users.ini as described above works. I don't have the problem of being logged out randomly after about half an hour.

However, shouldn't webtrees renew the session whenever I interact with it (interaction being opening some page in my tree)? For the average webtree instance, it is probably ok to have the session lifetime increased to 12 or 24 hours, but in general, there is a security benefit to keep the session lifetime low, given that the session is renewed upon every interaction.

fisharebest commented 11 months ago

There are other interesting settings for session that might be relevant. For example, cookie_lifetime.

mathiasbockwoldt commented 10 months ago

I investigated a bit further. Using the following settings, I could remove the randomness from the problem and reducing the time made it fail (relatively) fast. The session cookie is not deleted as long as the browser is kept open.

session.cookie_lifetime    0
session.gc_divisor       100
session.gc_maxlifetime   120
session.gc_probability   100

The reproducible behaviour is such that I can happily do whatever I want after login for exactly 2 minutes. After that, the next action (editing, reading, whatever) will tell me that I am not logged in.

This looks to me like the session is created, but never updated. In my understanding, the session timeout (in this case 2 minutes) should be extended whenever I open a page inside the webtrees folder. Only after gc_maxlifetime seconds, the session should be marked for deletion and eventually garbage collected. But if I do something within the lifetime, the lifetime should be extended, right? This does not seem to happen.

Now, I can't see the internal session timestamp that php stores somewhere. But I added a logger to Session.php right below the session_start() call (line 84) to see if that is called. And it is called between one and many times everytime I open a webtrees page. So I don't really understand, why the session timestamp is not updated.

Inspecting the session data, I can see is that _GUEST_sessiontime is never updated in the $_SESSION variable after it is set initially.

Please tell me, if there is anything more I can test to help in this issue.

Jefferson49 commented 7 months ago

In order to test the potential influence of the garbage collection, I tried a rather extreme configuration:

Now, I can reproduce the log off behavior! Since the chosen configuration forces the garbage collection to run every second, I get logged off after every second mouse click in webtrees.

I hope this makes the issue reproducible and helps to analyse the root cause.

Jefferson49 commented 7 months ago

During session garbage collection, the following method in SessionDatabaseHandler.php is called:

public function gc($max_lifetime)
{
    return DB::table('session')
        ->where('session_time', '<', date('Y-m-d H:i:s', time() - $max_lifetime))
        ->delete();
}

Before the garbage collection, the session table looks like this:

session_table_before_garbage_collection

If the method above is called, the complete entry in the session table is deleted including the user id. I guess this is the reason why the user gets logged off.

Jefferson49 commented 6 months ago

Thank you very much for fixing this issue, which was reported many times!

While testing the new code, I observed that the session_time was updated any time and not only once a minute. It seems that the code inside the following if condition in line 116 is always entered:

            // Only update session once a minute to reduce contention on the session table.
            if ($now->subtractMinutes(1)->timestamp() > Registry::timestampFactory()->fromString($this->row->session_time)->timestamp()) {
                $updates['session_time'] =  $now->toDateTimeString();
            }

It seems that the $now variable gets changed by the statement ($now->subtractMinutes(1)) in the if clause; and afterwards, the changed value (i.e. one minute less) is stored to the database. I am not sure if this was intended.

I tried to visualize this in the debugger by adding two debug variables before and after the if condition:

session_time

fisharebest commented 6 months ago

Are you testing just this change - or are you testing the latest code?

There was a recent fix to make the Timestamp class immutable. If you don't also have that fix, then I would expect this code to fail as you describe.

webtrees-pesz commented 6 months ago

Hello Greg,

are other fixes required to solve the problem correctly? if yes, which ones?

Jefferson49 commented 6 months ago

Are you testing just this change - or are you testing the latest code?

Yes, I was testing with the latest change of the file SessionDatabaseHandler.php only.

There was a recent fix to make the Timestamp class immutable. If you don't also have that fix, then I would expect this code to fail as you describe.

Thank you very much for the hint! After additionally using the latest version of Timestamp.php, the issue with the decreased $now variable disappeared. Now, the test looks good in my installation.