Install and Infrastructure Hardening
Hardening a Drupal installation running the TFA module involves both filesystem clean-up and runtime infrastructure configuration (particularly caching).
Remove unnecessary files
Unnecessary files may be removed in order to reduce the amount of information available to attackers regarding the version of TFA deployed.
The following paths are safe to remove:
Using the Drupal Vendor Hardening Composer Plugin, the following configuration in your root composer.json will remove the listed directories during install:
Note
The Drupal Vendor Hardening plugin only removes directories; it will not remove individual files.
Cache Infrastructure Hardening (cache.tfa_memcache)
TFA relies on a dedicated cache bin (cache.tfa_memcache) to store request-scoped security flags, including:
- tfa_complete (UID validated by TfaUserAuth in the current request)
- tfa_auth_method_bypass_approved (UID approved by an exempted authentication provider)
- tfa_account_switcher_bypass (UID approved during an active account_switcher switch)
Security Requirement: Non-Persistent Storage
Critical Security Requirement
It is security-critical that the tfa_memcache cache bin utilizes only non-persistent, request-scoped in-memory storage (cache.backend.memory).
If cache.tfa_memcache is redirected to a persistent or shared cache backend (such as Redis, Memcached, APCu, or database cache tables), security flags could persist across separate requests or leak between different user sessions, creating a severe vulnerability.
Configuring Shared Cache Backends (Redis / Memcached)
When configuring global cache backends in settings.php, ensure that tfa_memcache is explicitly pinned to cache.backend.memory:
// Example settings.php snippet for sites using Redis:
$settings['redis.connection']['interface'] = 'PhpRedis';
$settings['redis.connection']['host'] = '127.0.0.1';
$settings['cache']['default'] = 'cache.backend.redis';
// CRITICAL: Ensure TFA memory cache remains request-scoped and non-persistent.
$settings['cache']['bins']['tfa_memcache'] = 'cache.backend.memory';
// Example settings.php snippet for sites using Memcache:
$settings['cache']['default'] = 'cache.backend.memcache';
// CRITICAL: Ensure TFA memory cache remains request-scoped and non-persistent.
$settings['cache']['bins']['tfa_memcache'] = 'cache.backend.memory';
Verifying Cache Bin Configuration
Verify that the bin resolves to Drupal\Core\Cache\MemoryBackend using Drush:
Drupal\Core\Cache\MemoryBackend.
Persistent Application Runtimes (FrankenPHP / Swoole / RoadRunner)
When deploying Drupal on persistent application runtimes (such as FrankenPHP in worker mode, Swoole, RoadRunner, or PHP-PM), the PHP memory state and service container persist across multiple HTTP requests within the same worker thread.
To prevent memory cache flags (tfa_complete, tfa_auth_method_bypass_approved) from bleeding across requests on persistent workers:
* Ensure that request termination listeners reset or flush memory cache bins between consecutive requests.
* Verify worker process isolation in staging before deploying persistent worker runtimes to production.