2FAuth Rust compatibility implementation — 0.3.0
Targets 2FAuth 8.0.3, upstream commit 3516c776a1fcbd83d234efc007e3a49807d6ed91. AGPL-3.0-only; upstream source and frontend provenance are retained. See README.ru.md for deployment/configuration instructions in Russian.
This is not a certified complete PHP replacement. Current evidence and remaining gaps are in compatibility/CURRENT.md. Never infer total coverage from test counts or from displaying the original Vue frontend.
Implemented areas include OTP/URI/export, Laravel encryption and rotation, account/group CRUD, per-user orders/groups, sharing and ownership, registration/profile/password recovery, Passport RSA bearer/PAT and PHP browser cookie interoperability, migrated WebAuthn credentials, SSO/proxy authentication, imports/icons/QR, preferences/settings, SMTP notifications and authentication/OTP auditing. The original Vue build is served, including subdirectory mounting.
Build and test
A current stable Rust toolchain, C compiler, make and Perl are required. OpenSSL is vendored for WebAuthn; no external OpenSSL development package is required.
cargo fmt --all -- --check
cargo clippy --locked --all-targets -- -D warnings
cargo test --locked --all-targets
cargo build --locked --release
python3 tests/http_smoke.py target/release/twofauth-rs
python3 tests/differential_harness.py
python3 tests/laravel_session_http.py target/release/twofauth-rs
PHP_BINARY=/path/to/php python3 tests/oauth_interop.py target/release/twofauth-rs
PHP_BINARY=/path/to/php python3 tests/device_interop.py target/release/twofauth-rs --output compatibility/device-interop.json
python3 tests/crypto_interop.py --check-php
The PHP crypto check requires PHP/OpenSSL. Full reference runs additionally require PHP 8.4+, locked Composer dependencies and the PHP extensions required by the pinned upstream.
python3 tools/run_reference.py --php /path/to/php \
--source ../upstream --candidate-binary target/release/twofauth-rs \
--candidate-db native --semantic-checks --passport-interop \
--extra-cases compatibility/cases.oauth.json --extra-cases compatibility/cases.device.json --output compatibility/reference-results.native.json
python3 tools/run_reference.py --php /path/to/php \
--source ../upstream --candidate-binary target/release/twofauth-rs \
--candidate-db laravel-copy --semantic-checks --passport-interop \
--extra-cases compatibility/cases.oauth.json --extra-cases compatibility/cases.device.json --output compatibility/reference-results.laravel.json
Each run uses disposable databases, credentials, application state and isolated server ports. Semantic login/QR checks precede the extra OAuth error burst because the PHP unnamed OAuth throttle shares its bucket with password login. The Laravel-copy mode runs real PHP migrations, seeds a synthetic user, copies the database through SQLite backup, and invokes prepare-sqlite. Do not point differential tests at live services.
tools/passport_interop.py --help documents the separate bidirectional Passport and PHP-browser-session upgrade test. It creates disposable fixture material rather than shipping deployment keys.
Local development
mkdir -p data
cargo run -- init
RUST_COOKIE_SECURE=false cargo run -- serve
Open http://127.0.0.1:8080; the first self-registered user becomes administrator. init refuses an existing users table. prepare-sqlite validates an already migrated Laravel SQLite schema and adds Rust-only session/ceremony metadata. serve also creates this metadata if absent after validation; it never runs application migrations or resets user tables.
Preserve original APP_KEY, APP_PREVIOUS_KEYS, Passport key files and storage. DATABASE_URL overrides Laravel DB_DATABASE; only SQLite is implemented. DB_CONNECTION selecting another driver fails explicitly. All switching exercises must use a backup/copy until complete compatibility is established.
The included Dockerfile/Compose were updated for static assets, vendored cryptography and writable storage. Docker itself was unavailable in the development environment, so image build/run is not claimed verified.
Laravel sessions and OAuth additions
File and SQLite database Laravel sessions can be imported using the original APP_KEY, SESSION_COOKIE, SESSION_DRIVER, SESSION_TABLE, SESSION_ENCRYPT and STORAGE_PATH. JSON and scalar/array PHP serialization are supported; PHP objects and references are rejected. Both store encryption and remember-me recallers are checked with real pinned PHP fixtures. Native session rotation destroys the imported store; logout rotates remember tokens. Redis, cookie and other session drivers remain outside this implementation.
Standard /oauth/token supports authorization-code/PKCE, refresh rotation, client credentials and device authorization/polling using the actual Defuse PHP encrypted wire format and Passport RSA keys. The pinned application registers Passport JSON management routes too late and lacks an authorization view binding. Defaults preserve the observed disabled/broken management and consent behavior. PASSPORT_JSON_API_ROUTES=true and RUST_OAUTH_CONSENT_ENABLED=true explicitly enable repaired management and consent. These optional routes are extensions, not an assertion that the original defects were absent.
SQLite startup now checks used application columns, primary/unique keys and foreign-key delete actions against the real migrated schema before adding Rust metadata. See compatibility/database-portability.md for the remaining engine-specific work.