Using an authentication provider to keep a user permanently logged in eventually causes session problems
I presume it's because the session has expired in some way?

First you need to understand how this happens.

Configuring Garbage Collection
When a session opens, PHP will call the gc handler randomly
according to the probability set by session.gc_probability /
session.gc_divisor. For example if these were set to 5/100
respectively, it would mean a probability of 5%. Similarly, 3/4 would
mean a 3 in 4 chance of being called, i.e. 75%.
If the garbage collection handler is invoked, PHP will pass the value
stored in the php.ini directive session.gc_maxlifetime. The
meaning in this context is that any stored session that was saved more
than gc_maxlifetime ago should be deleted. This allows one to expire
records based on idle time.
However, some operating systems (e.g. Debian) do their own session
handling and set the session.gc_probability variable to 0 to stop
PHP doing garbage collection. That's why Symfony now overwrites this
value to 1.
If you wish to use the original value set in your php.ini, add the
following configuration:
# config/packages/framework.yaml
framework:
    session:
        gc_probability: null

Source: Symphony's official docs on Configuring Sessions and Save Handlers

In Drupal 8 &amp; 9 you can see these gc settings in default.services.yml
Possible Solutions on how to stay logged in longer.
In /sites/default/settings.php uncomment
 if (file_exists($app_root . '/' . $site_path . '/settings.local.php')) {
   include $app_root . '/' . $site_path . '/settings.local.php';
 }

then copy /sites/example.settings.local.php and rename to /sites/default/settings.local.php
Now you can use /sites/development.services.yml to override those settings, for example
(I used these numbers for testing so it logs me out after 2 seconds):
parameters:
  session.storage.options:
    gc_probability: 1
    gc_divisor: 1
    gc_maxlifetime: 2
    cookie_lifetime: 2

I tried setting gc_probability to 0 or null, which should stop it, but the gc() function still fired. Perhaps it's reading the value from php.ini
So alternatively you could set the gc_maxlifetime and cookie_lifetime to not expire decades from now. See set a cookie to never expire.