Your admin login now takes an authenticator app
One password is a thin line of defence for an admin interface that can publish to every webspace you run.
Sulu has supported two-factor authentication for a while, but in practice most teams stopped at the email method. It works, it is easy to explain to editors, and it depends on a mailbox that is often protected by exactly one password itself. Authenticator apps solve that. They work offline, they do not depend on the user's mailbox at all, and enterprise security policies ask for them by name.
The pieces existed in the Symfony ecosystem. scheb/2fa-totp has been battle-tested for years, and Sulu already builds on that open source bundle. What was missing was the part nobody enjoys building, the guided setup inside the admin interface: show a QR code, verify a first code before anything is switched on, hand out backup codes, and give administrators a way to reset all of it when a phone is lost.
That part now exists, and we did not write it.
The code came from adesso
adesso is a Sulu Gold partner, and they hit this requirement in a customer project. Instead of keeping the workaround in their own fork, the adesso team built the feature properly and offered it upstream. What arrived was not a feature request with a rough sketch attached. It was working code, against a real project, with the edge cases already found.
That changes the economics of a contribution completely. Our part was review, hardening, and integration: making the flow safe against half-finished enrolments, aligning it with how Sulu builds admin forms, and getting it through CI. The design decisions had already been proven in production.
That also means the feature does not arrive as project-specific code that happens to work in Sulu. It becomes part of Sulu, follows the same patterns as the rest of the admin, and can be maintained with the platform.
Two pull requests carry the work:
- #8959 adds the authenticator app (TOTP) setup, backup codes, and the administrative reset.
- #8972 extends the same guided setup to the
googlemethod, so projects already runningscheb/2fa-google-authenticatorget the identical experience without swapping packages.
Both are merged and released. The work went into 2.6 first and was then synced into 3.0, so it is out in Sulu 2.6.26 and Sulu 3.0.9. The setup is documented in the SecurityBundle reference.
Setup without the lockout risk
Two-factor authentication is only useful if people can actually enrol without creating another support ticket. The new setup stays inside the Sulu profile and does not activate anything until the first code has been verified.
Open your profile in the admin interface and pick the authenticator app method. You get a QR code and the secret in plain text for password managers that prefer typing over scanning. Scan it with Microsoft Authenticator, 1Password, Secure Envoy, or whatever your organisation has standardised on, then enter the first generated code. That confirmation step is the important one.
Nothing is activated until the code checks out, which means you cannot lock yourself out by closing the overlay halfway through. The profile endpoint enforces the same rule server side and rejects an attempt to switch TOTP on without a confirmed setup.
Switching between methods clears the secrets of the others, so an abandoned enrolment from three weeks ago cannot quietly become an active login factor.
Backup codes come from the same overlay when scheb/2fa-backup-code is enabled. They are shown once, stored hashed, and generated on demand. Existing plaintext codes from older setups keep working, so nothing breaks on update.
One detail worth checking before you roll this out: Sulu previously configured TOTP with a non-standard 20 second period and 8 digits. It now uses the standard 30 seconds and 6 digits, which is what authenticator apps expect out of the box.
When someone loses their phone
Every 2FA rollout eventually produces the same support ticket. Two answers ship with this:
bin/adminconsole sulu:security:user:reset-two-factor <username>
For anyone who does not have shell access, a reset action sits in the toolbar on the user's permissions tab, behind a confirmation dialog. Both paths write an activity event, so the reset shows up in the audit trail rather than happening invisibly. You get a recovery path without creating a blind spot for administrators.
Combine that with sulu_security.two_factor.force, which takes a pattern matched against user email addresses, and you get a workable policy: force two factor for everyone in your organisation, reset a user, and the next login walks them through setup again. Note that forcing activates the email method as the baseline and never overrides a method a user has already enrolled, so an editor with an authenticator app stays on the authenticator app.
If you want to soften the daily friction, add scheb/2fa-trusted-device and let people mark their own laptop as trusted so it skips the second factor. The login flow itself is untouched core, so none of this asks you to replace Sulu's authentication.
Making the setup flow reusable
The implementation matters beyond TOTP. We did not want to hardcode another authentication method into the admin interface and repeat the work the next time one was added. Getting there required two changes that were harder than they looked.
The first was the profile form. Field types render where the form XML puts them, and a multi-step setup flow that has to appear at a specific point in the profile needed the form building to bend around it.
The second was the compiler pass. Which two-factor methods Sulu offers depends on which scheb services are actually registered in your container, so that decision had to be overridden rather than hardcoded.
That is why #8972 could add the google method later without touching the setup flow at all.
Neither is glamorous. But it means the next authentication method does not have to start from zero.
Why this lands in 2.6
Sulu 2.6 is the LTS. New features normally go to the current minor, and by the letter of that rule this belongs in 3.1. We made an exception, for two reasons.
The first is where the users are. Long-term support releases are where security requirements land hardest, because that is what regulated and enterprise projects run. Telling those teams that authenticator-based two-factor authentication is available if they upgrade a major version is not a useful answer.
The second is the partner. adesso did the work, adesso needs it in 2.6, and a partnership that only flows in one direction is not a partnership. When someone hands you production-quality code for a gap you have on your own list, meeting them where they are is the least you can do.
The dependencies stay optional. You install scheb/2fa-totp, scheb/2fa-backup-code, and spomky-labs/otphp 11.1 or newer if you want this, and nothing changes for projects that do not. The feature is out now, in 2.6.26 and in 3.0.9.
From one project to the Sulu ecosystem
This started as one customer requirement in one project. It ends up as authentication that every Sulu installation can switch on.
That loop is the part of open source that is easy to describe and hard to make happen. Partners sit close to the requirements of complex projects. We maintain the platform and its architecture. When the two meet, something built for one project becomes part of the platform for everyone.
The adesso work is that model doing what it is supposed to do. Their customer gets the capability they needed. Nobody else has to build it a second time. And a piece of enterprise functionality that could have stayed proprietary in a fork is open source instead.
That is also what the Sulu Partner Program is for: closer technical collaboration, direct access to the core team, architecture guidance, and input into where the platform goes next.
Conclusion
If you are running Sulu behind a security policy that needs authenticator apps, update to 2.6.26 or 3.0.9, add the optional packages, and try the flow. Bug reports and feedback go to github.com/sulu/sulu, and if you are sitting on a fix in your own fork the way adesso was, we would rather review it than have you maintain it alone.
If your agency is building with Sulu and wants that kind of collaboration with the core team, take a look at the Sulu Partner Program.
