Email-based Two-Factor Authentication (2FA) extension for FOSSBilling. Adds an extra layer of security to your billing system by requiring users to verify their identity with a code sent to their email after entering their password.
- Email-Based Verification: Sends 6-digit codes via email
- Branded Emails: Uses FOSSBilling's template system with company logo and signature
- Login Interception: Seamlessly integrates into existing login workflow
- Rate Limiting: Maximum 3 verification attempts to prevent brute-force attacks
- Code Expiration: Codes automatically expire after 10 minutes
- User Control: Clients can enable/disable 2FA for their own accounts
- Admin Management: Administrators can manage 2FA for all users
- Enforcement Policies: Optional mandatory 2FA for admins and/or clients
- Statistics Dashboard: Track 2FA usage and successful verifications
- Session Security: Partial authentication state prevents session hijacking
- Database Cleanup: Automatic cleanup of expired codes via cron
- FOSSBilling: Version 0.6 or higher
- PHP: Version 7.4 or higher
- PHP Extensions: cURL, PDO, mbstring
- Database: MySQL 5.7+ or MariaDB 10.3+
- SMTP: Configured email system in FOSSBilling
- Email Access: Users must have access to their email accounts
-
Download the extension
cd /var/www/fossbilling/bb-modules/ git clone https://github.com/AXYNUK/fossbilling-2fa-email.git Twofactor -
Set permissions
chown -R www-data:www-data Twofactor chmod -R 755 Twofactor
-
Activate extension
- Login to FOSSBilling admin panel
- Navigate to Extensions โ Available Extensions
- Find "Two-Factor Authentication (Email)"
- Click Activate
-
Verify installation
- Database tables
twofactor_codes,twofactor_settings, andextension_metashould be created - Navigate to System โ Two-Factor Authentication to configure
- Database tables
- Navigate to Extensions โ Extension Directory
- Search for "Two-Factor Authentication"
- Click Install
- Click Activate
Navigate to Admin Panel โ System โ Two-Factor Authentication
- Enable Extension: Master switch for 2FA functionality
- Code Expiry Time: How long codes remain valid (default: 10 minutes)
- Maximum Attempts: Number of code entry attempts before lockout (default: 3)
- Require 2FA for Admins: Makes 2FA mandatory for all administrators
- Require 2FA for Clients: Makes 2FA mandatory for all clients
โ ๏ธ Warning: Enabling enforcement may lock out users without email access. Test thoroughly before enabling in production.
Clients can manage their own 2FA:
- Login to client area
- Navigate to Account โ Two-Factor Authentication
- Click Enable 2FA to activate
- Click Disable 2FA to deactivate
โโโโโโโโโโโโโโโโโโโ
โ Enter Username โ
โ & Password โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ Credentials โ
โ Validated โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโ
โ 2FA Enabled?โ
โโโโโโโโฌโโโโโโโ
โ
YESโโโโดโโโNO
โ โ
โผ โผ
โโโโโโโโโโโ โโโโโโโโโโโโ
โ Send โ โ Direct โ
โ Code โ โ Access โ
โ Email โ โ Dashboardโ
โโโโโโฌโโโโโ โโโโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ Verification โ
โ Page โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโโโโ
โ Enter Code โ
โ from Email โ
โโโโโโโโโโฌโโโโโโโโโ
โ
โผ
โโโโโโโโโโโโ
โ Valid? โ
โโโโโโฌโโโโโโ
โ
YESโโโดโโNO
โ โ
โผ โผ
โโโโโโโโโโ โโโโโโโโโโ
โAccess โ โ Error โ
โGranted โ โTry Againโ
โโโโโโโโโโ โโโโโฌโโโโโ
โ
โผ
โโโโโโโโโโโโโโโโ
โMax 3 Attemptsโ
โThen Re-login โ
โโโโโโโโโโโโโโโโ
The 2FA email automatically includes:
- Company logo (from FOSSBilling settings)
- Company name
- 6-digit verification code (prominently displayed)
- Expiration warning (10 minutes)
- Security instructions
- Company signature (if configured)
Example:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ [COMPANY LOGO] โ
โ โ
โ Two-Factor Authentication โ
โ โ
โ Hello John Doe, โ
โ โ
โ Your verification code: โ
โ โ
โ โโโโโโโโโโโโโโโ โ
โ โ 123456 โ โ
โ โโโโโโโโโโโโโโโ โ
โ โ
โ โ ๏ธ Expires in 10 minutes โ
โ โ
โ Didn't request this? โ
โ Contact support immediately. โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Codes are generated using PHP's random_int() function, which provides cryptographically secure random numbers:
$code = random_int(100000, 999999); // 6-digit secure codeThe system implements strict rate limiting:
- Maximum 3 attempts per verification session
- After 3 failed attempts, user must re-login
- Attempt counter stored in database
- Session cleared on max attempts
- Codes expire 10 minutes after generation (configurable)
- Expiration time stored in database
- Expired codes automatically rejected
- Cleanup cron removes old codes
During 2FA verification:
- No session established until code verified
- Temporary session variables:
twofactor_pending: Boolean flagtwofactor_user_id: User ID (not username)twofactor_user_type: 'admin' or 'client'twofactor_attempts: Attempt counter
- Full session only granted after successful verification
Email addresses are masked in UI:
john.doe@example.comโjo****e@example.com- Prevents email address leakage
Track 2FA usage:
- Codes Sent Today: Number of 2FA codes sent
- Successful Logins Today: Completed 2FA verifications
- Admins with 2FA: Count of admins using 2FA
- Clients with 2FA: Count of clients using 2FA
- View all administrators with 2FA status
- Enable/disable 2FA for specific admins
- Override user preferences with enforcement policies
- Cleanup Expired Codes: Manually trigger database cleanup
- Automatic cleanup runs daily via cron
Run the comprehensive test suite:
cd /var/www/fossbilling/bb-modules/Twofactor/
php test_twofactor.phpExpected output:
========================================
FOSSBilling 2FA Extension Test Suite
========================================
Running: Test 1: Generate 6-digit verification code
โ PASSED
[... 15 tests ...]
========================================
TEST RESULTS
========================================
Total Tests: 15
Passed: 15
Failed: 0
Success Rate: 100.00%
========================================
โ ALL TESTS PASSED!
Extension is ready for production use.
See TEST_PLAN.md for comprehensive integration test cases.
-
Check SMTP Settings
- Navigate to Admin โ Settings โ Email
- Verify SMTP credentials are correct
- Test email sending
-
Check Spam Folder
- 2FA emails may be flagged as spam
- Add sender to whitelist
-
Check Email Logs
- Review FOSSBilling email logs
- Check for email sending errors
-
Check Expiration
- Codes expire after 10 minutes
- Request a new code if expired
-
Check Attempts
- Maximum 3 attempts per session
- Re-login if attempts exceeded
-
Check Code Entry
- Ensure all 6 digits entered
- No spaces or special characters
For Admins:
- Access database directly
- Disable 2FA for user:
UPDATE twofactor_settings SET enabled = 0 WHERE user_id = [USER_ID] AND user_type = 'admin';
- User can now login without 2FA
For Clients:
Contact support to disable 2FA from admin panel.
-
Check PHP Requirements
php -v # Should be 7.4+ php -m | grep -E 'curl|pdo|mbstring'
-
Check Permissions
ls -la /var/www/fossbilling/bb-modules/Twofactor # Should be owned by web server user -
Check Error Logs
tail -f /var/log/fossbilling/error.log
Verify a 2FA code.
Parameters:
code(string, required): 6-digit verification code
Returns:
{
"success": true,
"redirect": "/admin"
}Resend verification code.
Parameters: None
Returns:
{
"success": true,
"message": "A new verification code has been sent to your email."
}Check if 2FA is enabled for current client.
Parameters: None
Returns:
{
"enabled": true
}Enable 2FA for current client.
Parameters: None
Returns: true
Disable 2FA for current client.
Parameters: None
Returns: true
Get extension settings.
Parameters: None
Returns:
{
"enabled": "1",
"code_expiry_minutes": "10",
"max_attempts": "3",
"enforce_for_admins": "0",
"enforce_for_clients": "0"
}Update extension settings.
Parameters:
enabled(string): "1" or "0"code_expiry_minutes(string): Minutes (1-60)max_attempts(string): Attempts (1-10)enforce_for_admins(string): "1" or "0"enforce_for_clients(string): "1" or "0"
Returns: true
Enable 2FA for a specific admin.
Parameters:
admin_id(int, required): Admin ID
Returns: true
Disable 2FA for a specific admin.
Parameters:
admin_id(int, required): Admin ID
Returns: true
Get 2FA status for all admins.
Parameters: None
Returns:
[
{
"id": 1,
"name": "John Doe",
"email": "john@example.com",
"twofactor_enabled": 1
}
]Get 2FA statistics.
Parameters: None
Returns:
{
"codes_sent_today": 15,
"successful_verifications_today": 12,
"clients_with_2fa": 45,
"admins_with_2fa": 3
}Cleanup expired verification codes.
Parameters: None
Returns:
{
"success": true,
"deleted_count": 23
}Twofactor/
โโโ Api/
โ โโโ Admin.php # Admin API endpoints
โ โโโ Client.php # Client API endpoints
โ โโโ Guest.php # Public API endpoints
โโโ Controller/
โ โโโ Admin.php # Admin verification controller
โ โโโ Client.php # Client verification controller
โโโ html_admin/
โ โโโ mod_twofactor_admin_index.html.twig
โโโ html_client/
โ โโโ mod_twofactor_client_index.html.twig
โ โโโ mod_twofactor_verify.html.twig
โโโ html_email/
โ โโโ mod_twofactor_verification.html.twig
โ โโโ mod_twofactor_verification.txt.twig
โโโ bootstrap.php # Event hook registration
โโโ EventListener.php # Login interception hooks
โโโ Service.php # Core 2FA logic
โโโ install.php # Database installation
โโโ uninstall.php # Database cleanup
โโโ manifest.json # Extension metadata
Stores temporary verification codes.
| Column | Type | Description |
|---|---|---|
| id | INT(11) | Primary key |
| user_id | INT(11) | User ID |
| user_type | ENUM('client','admin') | User type |
| code | VARCHAR(6) | Verification code |
| attempts | INT(2) | Verification attempts |
| created_at | DATETIME | Creation timestamp |
| expires_at | DATETIME | Expiration timestamp |
| verified_at | DATETIME | Verification timestamp |
| ip_address | VARCHAR(45) | Client IP address |
Stores per-user 2FA preferences.
| Column | Type | Description |
|---|---|---|
| id | INT(11) | Primary key |
| user_id | INT(11) | User ID |
| user_type | ENUM('client','admin') | User type |
| enabled | TINYINT(1) | 2FA enabled flag |
| created_at | DATETIME | Creation timestamp |
| updated_at | DATETIME | Update timestamp |
Stores extension configuration.
| Column | Type | Description |
|---|---|---|
| id | INT(11) | Primary key |
| extension | VARCHAR(255) | Extension name |
| meta_key | VARCHAR(255) | Setting key |
| meta_value | TEXT | Setting value |
| created_at | DATETIME | Creation timestamp |
| updated_at | DATETIME | Update timestamp |
This extension is licensed under the Apache License 2.0.
Copyright 2025 AXYNUK
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
See LICENSE file for full text.
Contributions are welcome! Please follow these guidelines:
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Commit your changes (
git commit -m 'Add amazing feature') - Push to the branch (
git push origin feature/amazing-feature) - Open a Pull Request
- Follow PSR-12 coding standards
- Add PHPDoc comments to all methods
- Write unit tests for new features
- Update documentation
- Issues: GitHub Issues
- Documentation: README.md
- Test Plan: TEST_PLAN.md
- Website: https://www.axyn.co.uk
Developed by: AXYNUK
For: FOSSBilling Community
Year: 2025
Initial release:
- โ Email-based 2FA with branded templates
- โ Login interception for admin and client
- โ Rate limiting (3 attempts max)
- โ Code expiration (10 minutes)
- โ Admin management dashboard
- โ Client self-service settings
- โ Enforcement policies
- โ Statistics tracking
- โ Comprehensive test suite
- โ Full documentation
Future enhancements planned:
- SMS verification option
- TOTP (Google Authenticator) support
- Backup codes
- Trusted device remembering
- IP-based 2FA bypass
- Webhook notifications
- Advanced analytics
- Multi-language support
Made with โค๏ธ by AXYNUK for the FOSSBilling community