I’m encountering a problem with the Login extra in MODX 3 when using numeric usernames during the registration and confirmation process.
Here is the situation:
Users register using an 8-digit customer number (e.g., 12345678) as their username.
Registration works fine: a user object is created and a confirmation email is sent with a link.
However, when the user clicks the confirmation link, they are always redirected to the site’s error_page.
Upon investigating, I found that in core/components/login/processors/register.php, the method setCachePassword sends the activation data to the /useractivation/ registry like this:
Problem:
Since the username is purely numeric (e.g., 12345678), PHP automatically interprets the array key as an integer, not a string.
This means the message in the registry is stored with an integer key, whereas ConfirmRegister expects a string key matching the submitted username.
As a result, the activation process cannot find the correct activation message and redirects to the error_page.
Key technical point:
In PHP, numeric string array keys like ‘12345678’ are automatically cast to integers (12345678).
Thus, the intended username => password mapping is broken during registration, and confirmation always fails.
Question:
Is there a recommended way to handle numeric usernames with the Login extra?
Should the core Login processors be adjusted to handle this situation?
Any advice or best practices would be highly appreciated!
If the username is an integer, then the code adds a timestamp to the filename (line 290).
Usually a file is created (on registration) in core/cache/registry/login/useractivation with the name <username>.msg.php which is then used by the confirmation processor.
When the file name suddenly includes a timestamp (e.g. 20250429T141032-<username>.msg.php), it doesn’t get found anymore.
As it won’t be possible to change the MODX modFileRegister class, the best solution is probably to add a prefix to the user name when the registry is accessed in both processors (if you really need the usernames to be numbers).
So for example, change this line to $this->modx->registry->login->send('/useractivation/',array('USER_'.$this->user->get('username') => $password),array(
Using a consistent prefix across the board makes things cleaner for lookups and future-proofing. Just out of curiosity, have you run into any issues with using a prefix when integrating with other extras or custom snippets that expect the raw username?
In this case I do not use a prefix, because the confirmation mails are not needed. I would rather set a prefix using a hook so that no adjustments have to be made to the login extra.
The registration creates a cache file (with a ‘secret’) that is then used by the confirmation.
The prefix I proposed in my last post was only for the name of this cache file (and not for the user name). Such a change can only be done by altering the source code of the Login extra.
Another way to avoid any issues, would indeed be to change the user names by adding a prefix directly to the user name.
If you add a prefix to the usernames the users won’t be able to log in without the prefix, though there is a way you could bypass the login credentials check and check them yourself (adding the prefix) without modifying the login code. It involves a plugin. The details are here.
The issue just raised while i was testing with different usernames. 012345 worked and 123456 didn’t, that was confusing so i investigated a bit. Isn’t it in general more an issue of modFileRegister?
I don’t know of any PHP function that would distinguish between those two (assuming that both are strings or both are integers). Possibly there’s another reason they’re being treated differently. For example, one is in quotes and the other is not.
Sure. Like I pointed out in my first post, integers are processed differently in modFileRegister. I don’t know why, but there must have been a good reason why this exception for integers was implemented.
As the code in modFileRegister has been like this for many years now, suddenly removing the part that handles integers differently will likely break other code that uses this class.
It’s much safer (in my opinion) to change the code in the Login extra, which won’t have any unexpected effects on other existing code.
A few minutes after posting the message above, I thought of an obvious PHP function that would treat them differently: md5() (or any hashing function).