Twofactor authentication and strong password
This commit is contained in:
@@ -0,0 +1,342 @@
|
||||
# Two-Factor Authentication (2FA) Implementation
|
||||
|
||||
## Overview
|
||||
|
||||
This document describes the two-factor authentication (2FA) implementation for the DBOIS application. The system supports two methods:
|
||||
|
||||
1. **Email OTP**: Users receive a one-time password via email
|
||||
2. **Google Authenticator**: Users use an authenticator app (Google Authenticator, Authy, etc.)
|
||||
|
||||
## Installation Steps
|
||||
|
||||
### 1. Database Migration
|
||||
|
||||
Run the SQL migration to add the necessary database tables and columns:
|
||||
|
||||
```bash
|
||||
mysql -u your_username -p your_database < application/migrations/001_add_two_factor_authentication.sql
|
||||
```
|
||||
|
||||
Or manually execute the SQL:
|
||||
|
||||
```sql
|
||||
-- Add 2FA columns to users table
|
||||
ALTER TABLE `users`
|
||||
ADD COLUMN `two_factor_enabled` VARCHAR(1) NOT NULL DEFAULT 'F' COMMENT 'T=enabled, F=disabled' AFTER `role`,
|
||||
ADD COLUMN `two_factor_method` VARCHAR(20) NULL DEFAULT NULL COMMENT 'email or authenticator' AFTER `two_factor_enabled`,
|
||||
ADD COLUMN `two_factor_secret` VARCHAR(255) NULL DEFAULT NULL COMMENT 'TOTP secret for Google Authenticator' AFTER `two_factor_method`;
|
||||
|
||||
-- Create table for email OTP codes
|
||||
CREATE TABLE `user_otp_codes` (
|
||||
`id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
`user_id` INT(11) UNSIGNED NOT NULL,
|
||||
`otp_code` VARCHAR(6) NOT NULL,
|
||||
`expires_at` TIMESTAMP NOT NULL,
|
||||
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
`used` VARCHAR(1) NOT NULL DEFAULT 'F' COMMENT 'T=used, F=not used',
|
||||
PRIMARY KEY (`id`),
|
||||
KEY `idx_user_id` (`user_id`),
|
||||
KEY `idx_expires_at` (`expires_at`),
|
||||
CONSTRAINT `fk_otp_user` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE CASCADE
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
||||
|
||||
-- Create index for faster lookups
|
||||
CREATE INDEX `idx_users_two_factor` ON `users` (`two_factor_enabled`, `two_factor_method`);
|
||||
```
|
||||
|
||||
### 2. File Structure
|
||||
|
||||
The following files have been created/modified:
|
||||
|
||||
#### New Files:
|
||||
- `application/libraries/TwoFactorAuth.php` - TOTP library for Google Authenticator
|
||||
- `application/models/beheer/UserOtp_model.php` - Model for managing email OTP codes
|
||||
- `application/libraries/beheer/twofactor/SendOtpEmail.php` - Library for sending OTP emails
|
||||
- `application/controllers/beheer/TwoFactorController.php` - Controller for 2FA settings
|
||||
- `application/views/pages/beheer/twofactor/settings_view.php` - 2FA settings page
|
||||
- `application/views/pages/login/verify2fa_view.php` - 2FA verification page during login
|
||||
- `application/views/emails/twofactor_otp_email.php` - Email template for OTP codes
|
||||
- `application/migrations/001_add_two_factor_authentication.sql` - Database migration
|
||||
|
||||
#### Modified Files:
|
||||
- `application/controllers/Login.php` - Added 2FA verification logic
|
||||
- `public/js/lib/modules/login/loginModule.js` - Updated to handle 2FA redirect
|
||||
|
||||
## Usage
|
||||
|
||||
### For End Users
|
||||
|
||||
#### Enabling 2FA
|
||||
|
||||
1. Log in to the application
|
||||
2. Navigate to: `/beheer/TwoFactorController`
|
||||
3. Select a 2FA method:
|
||||
- **Email**: Receive codes via email
|
||||
- **Google Authenticator**: Use an authenticator app
|
||||
|
||||
#### Email Method Setup
|
||||
|
||||
1. Click on "E-mail" card
|
||||
2. Click "2FA Inschakelen" (Enable 2FA)
|
||||
3. Done! You'll receive OTP codes via email on each login
|
||||
|
||||
#### Google Authenticator Method Setup
|
||||
|
||||
1. Click on "Google Authenticator" card
|
||||
2. Click "2FA Inschakelen" (Enable 2FA)
|
||||
3. A QR code will appear
|
||||
4. Scan the QR code with your authenticator app (Google Authenticator, Authy, etc.)
|
||||
5. Enter the 6-digit code from your app to verify
|
||||
6. Click "Verifiëren" (Verify)
|
||||
7. Done! You'll use the authenticator app on each login
|
||||
|
||||
#### Changing 2FA Method
|
||||
|
||||
1. Go to 2FA settings page
|
||||
2. Select a different method
|
||||
3. Click "Methode Wijzigen" (Change Method)
|
||||
4. If switching to authenticator, scan the new QR code and verify
|
||||
|
||||
#### Disabling 2FA
|
||||
|
||||
1. Go to 2FA settings page
|
||||
2. Click "2FA Uitschakelen" (Disable 2FA)
|
||||
3. Confirm the action
|
||||
|
||||
#### Login with 2FA
|
||||
|
||||
1. Enter username and password as usual
|
||||
2. If 2FA is enabled, you'll be redirected to a verification page
|
||||
3. For email method:
|
||||
- Check your email for the 6-digit code
|
||||
- Enter the code on the verification page
|
||||
- Click "Verifiëren" (Verify)
|
||||
- Can resend code if needed
|
||||
4. For authenticator method:
|
||||
- Open your authenticator app
|
||||
- Enter the current 6-digit code
|
||||
- Click "Verifiëren" (Verify)
|
||||
|
||||
### For Administrators
|
||||
|
||||
#### Setting up Email Configuration
|
||||
|
||||
Ensure your CodeIgniter email configuration is properly set up in `application/config/email.php`. The system sends OTP emails from `noreply@dbois.nl`.
|
||||
|
||||
#### OTP Code Settings
|
||||
|
||||
OTP codes:
|
||||
- Are 6 digits long
|
||||
- Are valid for 10 minutes
|
||||
- Are automatically cleaned up after use or expiration
|
||||
|
||||
#### Google Authenticator Settings
|
||||
|
||||
- TOTP codes are generated using RFC 6238 standard
|
||||
- Codes are 6 digits long
|
||||
- Time step is 30 seconds
|
||||
- Verification allows ±30 seconds time window for clock drift
|
||||
|
||||
#### Monitoring and Maintenance
|
||||
|
||||
**Clean up expired OTP codes:**
|
||||
```php
|
||||
$this->load->model('beheer/UserOtp_model');
|
||||
$deletedCount = $this->UserOtp_model->cleanupExpiredOTPs();
|
||||
```
|
||||
|
||||
**Check user's 2FA status:**
|
||||
```php
|
||||
$user = $this->User_model->get($userId);
|
||||
if ($user->two_factor_enabled === 'T') {
|
||||
// User has 2FA enabled
|
||||
$method = $user->two_factor_method; // 'email' or 'authenticator'
|
||||
}
|
||||
```
|
||||
|
||||
## API Endpoints
|
||||
|
||||
### 2FA Settings Management
|
||||
|
||||
#### Get 2FA Status
|
||||
```
|
||||
GET /beheer/TwoFactorController/status
|
||||
Response: { enabled: boolean, method: string|null }
|
||||
```
|
||||
|
||||
#### Enable 2FA
|
||||
```
|
||||
POST /beheer/TwoFactorController/enable
|
||||
Data: { method: 'email'|'authenticator' }
|
||||
Response: {
|
||||
success: boolean,
|
||||
message: string,
|
||||
method: string,
|
||||
secret?: string (if authenticator),
|
||||
qrCodeUrl?: string (if authenticator)
|
||||
}
|
||||
```
|
||||
|
||||
#### Verify Authenticator Setup
|
||||
```
|
||||
POST /beheer/TwoFactorController/verifySetup
|
||||
Data: { code: string (6 digits) }
|
||||
Response: { success: boolean, message: string }
|
||||
```
|
||||
|
||||
#### Disable 2FA
|
||||
```
|
||||
POST /beheer/TwoFactorController/disable
|
||||
Response: { success: boolean, message: string }
|
||||
```
|
||||
|
||||
#### Change 2FA Method
|
||||
```
|
||||
POST /beheer/TwoFactorController/changeMethod
|
||||
Data: { method: 'email'|'authenticator' }
|
||||
Response: {
|
||||
success: boolean,
|
||||
message: string,
|
||||
method: string,
|
||||
secret?: string (if authenticator),
|
||||
qrCodeUrl?: string (if authenticator)
|
||||
}
|
||||
```
|
||||
|
||||
### Login Flow
|
||||
|
||||
#### Initial Login
|
||||
```
|
||||
POST /login
|
||||
Data: { username: string, password: string }
|
||||
Response (with 2FA): { result: '2FA-REQUIRED', method: string }
|
||||
Response (without 2FA): boolean
|
||||
```
|
||||
|
||||
#### Show 2FA Verification Page
|
||||
```
|
||||
GET /login/showVerify2fa
|
||||
Displays verification page with temporary session
|
||||
```
|
||||
|
||||
#### Verify 2FA Code
|
||||
```
|
||||
POST /login/verify2fa
|
||||
Data: { code: string (6 digits) }
|
||||
Response: { success: boolean, message: string }
|
||||
```
|
||||
|
||||
#### Resend OTP (Email method only)
|
||||
```
|
||||
POST /login/resendOtp
|
||||
Response: { success: boolean, message: string }
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
1. **Session Management**: During 2FA verification, only a temporary session with user ID is created. Full session is created only after successful 2FA verification.
|
||||
|
||||
2. **OTP Expiration**: Email OTP codes expire after 10 minutes and are marked as used after verification to prevent replay attacks.
|
||||
|
||||
3. **Time-Based Codes**: Google Authenticator codes are time-based with a 30-second window, making them resistant to replay attacks.
|
||||
|
||||
4. **Rate Limiting**: Consider implementing rate limiting on:
|
||||
- `/login/verify2fa` endpoint to prevent brute force
|
||||
- `/login/resendOtp` endpoint to prevent email flooding
|
||||
|
||||
5. **HTTPS**: The system enforces HTTPS in production (already implemented in MY_Controller).
|
||||
|
||||
6. **QR Code Security**: QR codes contain sensitive TOTP secrets. They should only be displayed over HTTPS and users should be advised to never share them.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Email OTP Not Received
|
||||
|
||||
1. Check email configuration in `application/config/email.php`
|
||||
2. Check spam/junk folders
|
||||
3. Use "Code opnieuw verzenden" (Resend code) button
|
||||
4. Check application logs for email send failures
|
||||
|
||||
### Authenticator Code Not Working
|
||||
|
||||
1. Ensure device time is synchronized (critical for TOTP)
|
||||
2. Check if user scanned the correct QR code
|
||||
3. Try codes within ±30 seconds window
|
||||
4. Re-setup authenticator if issues persist
|
||||
|
||||
### Locked Out of Account
|
||||
|
||||
If a user loses access to their 2FA method:
|
||||
|
||||
1. Admin can directly disable 2FA in database:
|
||||
```sql
|
||||
UPDATE users
|
||||
SET two_factor_enabled = 'F',
|
||||
two_factor_method = NULL,
|
||||
two_factor_secret = NULL
|
||||
WHERE id = [user_id];
|
||||
```
|
||||
|
||||
2. Admin should then securely verify user identity before re-enabling 2FA
|
||||
|
||||
### Session Issues
|
||||
|
||||
If users are stuck in 2FA verification:
|
||||
|
||||
1. Clear temporary session variables:
|
||||
```php
|
||||
$this->session->unset_userdata('pending_2fa_user_id');
|
||||
$this->session->unset_userdata('pending_2fa_method');
|
||||
```
|
||||
|
||||
2. User can click "Annuleren" (Cancel) to return to login page
|
||||
|
||||
## Testing
|
||||
|
||||
### Test Email Method
|
||||
|
||||
1. Enable 2FA with email method for test user
|
||||
2. Log out
|
||||
3. Log in with test user credentials
|
||||
4. Verify OTP code received via email
|
||||
5. Test "resend code" functionality
|
||||
6. Test expired code (wait 10+ minutes)
|
||||
7. Test invalid code
|
||||
|
||||
### Test Authenticator Method
|
||||
|
||||
1. Enable 2FA with authenticator method for test user
|
||||
2. Scan QR code with Google Authenticator app
|
||||
3. Verify setup code works
|
||||
4. Log out
|
||||
5. Log in with test user credentials
|
||||
6. Verify authenticator code
|
||||
7. Test with time-synced codes
|
||||
8. Test invalid code
|
||||
|
||||
### Test Method Switching
|
||||
|
||||
1. Enable with one method
|
||||
2. Switch to another method
|
||||
3. Verify new method works
|
||||
4. Disable 2FA
|
||||
5. Re-enable with different method
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
Possible improvements:
|
||||
|
||||
1. **Backup Codes**: Generate one-time backup codes for account recovery
|
||||
2. **Remember Device**: Option to skip 2FA on trusted devices for X days
|
||||
3. **SMS OTP**: Add SMS as a third 2FA method
|
||||
4. **Admin Dashboard**: View 2FA adoption metrics
|
||||
5. **Rate Limiting**: Implement built-in rate limiting for security
|
||||
6. **Audit Logs**: Log 2FA events (enable, disable, failed attempts)
|
||||
7. **Mandatory 2FA**: Require 2FA for specific user roles
|
||||
|
||||
## Support
|
||||
|
||||
For issues or questions, please contact the development team or refer to:
|
||||
- CodeIgniter Documentation: https://codeigniter.com/userguide3/
|
||||
- Google Authenticator: https://github.com/google/google-authenticator
|
||||
- RFC 6238 (TOTP): https://tools.ietf.org/html/rfc6238
|
||||
Reference in New Issue
Block a user