dazi-web / oxid2fa
Two-factor authentication (TOTP) for OXID eShop administrators
Requires
- php: ^8.2
- ext-sodium: *
- bacon/bacon-qr-code: ^3.0
- spomky-labs/otphp: ^11.3
- symfony/clock: ^6.4
- symfony/filesystem: ^6.3
Requires (Dev)
- oxid-esales/developer-tools: dev-b-7.3.x
- oxid-esales/graphql-base: ^12.0 || ^13.2
- oxid-esales/oxideshop-ce: dev-b-7.3.x
- phpmd/phpmd: ^2.15
- phpstan/phpstan: ^2.0.2
- phpunit/phpunit: ~10.5.17
- squizlabs/php_codesniffer: ^4.0
Suggests
- oxid-esales/graphql-base: ^12.0 || ^13.2: adds the twoFactorLogin query, to sign in to the GraphQL API with a code
Provides
None
Conflicts
- oxid-esales/oxideshop-ce: <7.3
Replaces
None
README
TOTP (RFC 6238) as second step of the admin login, with recovery codes, audit log, brute-force throttling and an administrative reset. Built on the shop's own authentication, without core changes.
Requirements: OXID eShop CE 7.3, PHP 8.2+, ext-sodium.
See docs/architecture.md for setup, architecture and security decisions.
Setup
composer require dazi-web/oxid2fa vendor/bin/oe-eshop-doctrine_migration migrations:migrate oxid2fa vendor/bin/oe-console oe:module:activate oxid2fa
- Activate the module. It creates its encryption key itself (
var/oxid2fa/encryption.key, outside the document root). - Settings: Admin → Extensions → Modules → oxid2fa → Settings: choose 2FA für Administratoren = optional or mandatory. The top of that page shows whether the key is fine.
- Done. Admins set up their authenticator app at Service → 2FA; with mandatory mode they are led through the setup at their next login.
Back up var/oxid2fa/encryption.key together with the database and keep it out of version control. Without it the
stored secrets cannot be read and the affected accounts have to be reset. Details: docs/architecture.md.
Other ways to sign in
Administrators who owe a second factor (2FA active, required for the account, or mandatory mode) are refused when they
sign in with a password alone anywhere but the admin area, for example through the shop front end or the GraphQL API
(2FA_LOGIN_REFUSED is logged).
With the GraphQL base module (version 12 or 13) installed, such an administrator
signs in to the API with the query twoFactorLogin(username, password, code). It returns the same access and refresh
token as login, and refresh renews the access token without a new code. The code is checked like in the admin
(attempt limit, no reuse). Without the GraphQL base module nothing changes.
Quality tools and tests
composer static # phpcs (PSR-12), phpstan level 8, phpmd: all three must be clean composer tests-unit # no shop, no database composer tests-database # real MariaDB/MySQL (OXID2FA_TEST_DB_* variables), no shop; includes parallel-process tests
License
MIT, see LICENSE.