Problem/Motivation

When Auto-generate keys is enabled in the module settings, creating a new user account causes an infinite loop and will exhaust server resources (memory or max execution time), resulting in a fatal error or an unresponsive site.

The root cause is in key_auth_user_insert() in key_auth.module. After setting the generated API key on the entity, it calls ->save() on the same entity that is currently being inserted:

$entity->set('api_key', $key_auth->generateKey())
  ->save(); // ← triggers hook_user_insert() again!

Calling ->save() inside hook_ENTITY_TYPE_insert() on the same entity re-invokes all insert hooks — including key_auth_user_insert() itself — leading to unbounded recursion.

Steps to reproduce

  1. Install the key_auth module.
  2. Enable Auto-generate keys at admin/config/services/key-auth.
  3. Grant the Use key authentication permission to the Authenticated user role.
  4. Create a new user account (via UI or drush).
  5. Observe a PHP fatal error (Maximum execution time exceeded or Allowed memory size exhausted) in the logs.

Proposed resolution

Replace hook_user_insert() with hook_user_presave() and set the API key directly on the entity object without calling ->save(). Since presave runs before the initial INSERT query, the key is persisted as part of the original save — no second save is needed.

An isNew() guard ensures the hook only acts on newly created users, not on updates.

function key_auth_user_presave(EntityInterface $entity) {
  if (!$entity->isNew()) {
    return;
  }
  if (\Drupal::config('key_auth.settings')->get('auto_generate_keys')) {
    $key_auth = \Drupal::service('key_auth');
    if ($key_auth->access($entity)) {
      $entity->set('api_key', $key_auth->generateKey());
    }
  }
}

A patch is attached.

Remaining tasks

  • Review the proposed fix.
  • Add a regression test that creates a user with auto_generate_keys enabled and asserts no recursive save occurs and the key is correctly stored.
  • Commit and release a patch release.

User interface changes

None.

API changes

None. The internal hook implementation changes from hook_user_insert to hook_user_presave, but no public API is affected.

Data model changes

None.

Comments

foxfabi created an issue. See original summary.

boinkster’s picture

That patch did not apply. Here's a re-rolled patch