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
- Install the
key_authmodule. - Enable Auto-generate keys at
admin/config/services/key-auth. - Grant the Use key authentication permission to the Authenticated user role.
- Create a new user account (via UI or drush).
- Observe a PHP fatal error (
Maximum execution time exceededorAllowed 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.
| Comment | File | Size | Author |
|---|---|---|---|
| #2 | key_auth-3587898-user-presave-autogenerate-key-1.patch | 1.03 KB | boinkster |
| key_auth_fix_user_insert.patch | 1.33 KB | foxfabi |
Comments
Comment #2
boinkster commentedThat patch did not apply. Here's a re-rolled patch