Introducing the OXID Security Module

Customer accounts hold addresses, order history and payment references, which makes them worth attacking. That's why we're introducing the OXID Security Module - a set of protections that strengthen the weak points of a shop's account and form handling, from password quality through bot defence to two-factor authentication.
The module bundles three feature areas that work independently. Enable what your shop needs and leave the rest switched off.
Why account security matters
Most attacks on a shop are not sophisticated. They are automated: credential stuffing against the login form, bots filling the contact and newsletter forms, weak passwords that fall to a dictionary in seconds. None of this needs a vulnerability in the shop software - it exploits the fact that forms are public and people reuse passwords.
The module answers those three patterns directly: it raises the cost of a weak password, it makes automated form submission unprofitable, and it puts a second factor between a stolen password and a customer's account.
Everything is configured in one place. In the shop administration, under Extensions -> Modules -> OXID Security Module -> Settings, the module adds three groups - one per feature area:
That single screen is the whole configuration surface, and the state you see above is the state you get after installing: password rules and bot protection on, two-factor authentication off.
Password policy
Password rules are enforced wherever a customer sets a password: registration, the password change in "My account", and the change form at the end of the forgot-password flow. Because the checks live in the shop's own input validation, they apply to the underlying model as well - not only to the form in the browser.
All of it is on by default, with a minimum length of eight characters. When a rule is violated, the customer sees every unmet requirement at once rather than one error at a time. One detail worth knowing if your shop already sets its own password length: the stricter of the two values wins - configure the module below the shop's setting and the shop's setting still applies. That is exactly what the help text behind the "?" next to Minimum length tells you.
To make a strong password easy rather than annoying, the module adds three things to the password fields: a live strength indicator with five levels, from very weak to very strong; a button that generates a strong password; and a show/hide toggle so people can check what they typed instead of guessing.
Captcha and honeypot protection
Public forms need to be usable by customers and unattractive to bots. The module offers two independent mechanisms.
The image captcha shows distorted characters that have to be typed back. Because a picture of text excludes anyone using a screen reader, it comes with an audio alternative: the characters are read out from pre-recorded audio - English and German are included - mixed with background noise. The image captcha uses PHP's GD extension, which is part of a standard OXID eShop setup.
The honeypot takes the opposite approach. It adds a trap to the form that a normal visitor never sees and never fills in, while automated submitters fall for it. There is nothing for the customer to solve and nothing to show in a screenshot - that is the point. It costs no usability at all, which is why it is worth leaving on even where you decide a captcha is too much friction.
Both protect the forms an attacker actually targets: contact, newsletter, registration, forgot-password, login (on the login page and in the header login box), and checkout without registration. Both are enabled by default, and each can be turned off on its own. A generated captcha stays valid for the configured period, 15 minutes by default.
Two-factor authentication
Two-factor authentication adds a one-time code to the login. After the password is accepted, the shop emails a six-digit code, and only entering that code completes the login.
Two notes before you switch it on. First, 2FA is disabled by default, both shop-wide and per customer: you enable it for the shop, and then each customer decides for their own account under My account -> Security. Nobody is locked out by an update. Second, the protection covers storefront logins and logins through the OXAPI - logins to the admin backend are not yet covered.
Two further mutations round out the flow: resendTwoFactorOtp re-issues the code for a pending challenge, and setTwoFactorAuth(enabled: true|false) lets an authenticated customer switch their own 2FA preference - the headless equivalent of the toggle in "My account".
This part of the module builds on OXID's GraphQL Base module. Its code is installed automatically as a Composer dependency, so there is nothing to fetch separately; you only need to activate it, and only if you want the API flow. Everything else in the module works without it.
Bringing the code email in line with your corporate design
The one-time code arrives in an HTML email whose subject and body are CMS content, editable per language in the admin backend - the same way you edit other shop emails. Change the wording, add your logo, match your colours.
If no CMS content is present, the shop sends a built-in default email, and every HTML mail ships with a plain-text fallback for clients that don't render HTML.
Compatibility
The module supports OXID eShop Compilation 7.5 and requires PHP 8.3 or a later 8.x release (tested up to PHP 8.5).
Installation
Install the module with Composer from the root directory of your shop:
composer require oxid-esales/security-module ^4.0.2
Then run the database migrations and activate the module:
./vendor/bin/oe-eshop-doctrine_migration migrations:migrate
./vendor/bin/oe-console oe:module:activate oe_security_module
For two-factor authentication through the OXAPI, also activate OXID's GraphQL Base module. It is already installed as a dependency; this command only switches it on:
./vendor/bin/oe-console oe:module:activate oe_graphql_base
