The MFA Plugin provides Two-Factor Authentication for GP247 system, enhancing user account security. The plugin supports multiple guards (customer, admin, vendor, pmo...) for flexible user authentication management.
- β Two-factor authentication using TOTP (Time-based One-Time Password)
- β Multiple guards support: customer, admin, vendor, pmo
- β Easy-to-scan QR codes with authenticator apps
- β Recovery codes for device loss scenarios
- β MFA management from Admin panel
- β Usage statistics by guard
- β Optional forced MFA per guard
- β Responsive and user-friendly interface
- β Multi-language support (Vietnamese, English)
- GP247 Core >= 1.2
- Laravel 12.x
- PHP >= 8.2
- Required packages:
- pragmarx/google2fa: ^8.0 or ^9.0
- bacon/bacon-qr-code: ^2.0 or ^3.0
Add the required packages to your main project's composer.json:
composer require pragmarx/google2fa
composer require bacon/bacon-qr-codeImportant: Run this command in the root directory of your GP247 project, not inside the plugin folder.
There are 4 methods to install the plugin:
- Navigate to "Extensions" in the admin dashboard
- Select "Plugins"
- Choose the "Install from Library" tab
- Find "MFA" plugin and click "Install"
- Click "Enable" to activate the plugin
- Access Admin Panel > Extensions > Plugins
- Select the "Import file" tab
- Choose the MFA plugin zip file
- Complete the import process
- Click "Enable" to activate the plugin
In case you encounter difficulties importing the zip file (e.g. upload errors, temporary file issues, etc.):
-
Unzip and copy the source code folder to the corresponding directory:
app/GP247/Plugins/MFA -
Copy the
MFA/publicfolder to the corresponding public path:public/GP247/Plugins/MFA -
Access Admin Panel > Extensions > Plugins
-
In the default "Local storage" tab, find "MFA" and click "Install"
-
Click "Enable" to activate the plugin
Since gp247 3.x you can download MFA from the GP247 library and install it straight from the command line, without opening the admin. Step 1 must be done first (composer require pragmarx/google2fa bacon/bacon-qr-code), otherwise the command stops because the packages are missing. Open a terminal in the website's root folder and run:
# 1) Once per website: register the (free) API License that connects the site to the GP247 library
php artisan gp247:ext-register-license
# 2) Download the plugin from the library and install it
php artisan gp247:ext-install --type=plugin --key=MFA- Before step 1, make sure
APP_URLin.envis the website's real domain (nothttp://localhost) β the license is bound to that domain. - Once installed, the plugin is enabled and caches are refreshed automatically; you no longer need to click Install/Enable in the admin.
- The command checks the requirements declared in
gp247.json(core version, composer packages, required plugins) and stops with a clear message if something is missing (e.g.pragmarx/google2faorbacon/bacon-qr-codeis not installed). - If the folder
app/GP247/Plugins/MFAis already on the server (copied manually or shipped with the installer), the command installs it in place instead of downloading it again. - The command refuses a plugin that is already installed. To move to a newer version, run
php artisan gp247:ext-update --type=plugin --key=MFA. - Append
--jsonto get machine-readable output (for scripts/CI). - The post-install configuration steps below (Step 3) still apply.
- More: Installing Plugins & Templates Β· Command reference.
Reference: Guide to Installing the Extension
After successful installation, the MFA plugin will appear in the menu: Admin Panel > System Configuration > Security > MFA
To configure the plugin, edit the file: app/GP247/Plugins/MFA/config.php
Default: The plugin is only enabled for the admin guard.
Configuration parameters for each guard:
- enabled:
1= enabled,0= disabled MFA for the guard - forced:
1= mandatory,0= optional (users can enable/disable MFA) - model: User model class
- qr_code_size: QR code size (100-500px)
- recovery_codes_count: Number of recovery codes (4-20)
- window: Time window allowance (0-5, recommended 1)
Example configuration:
'guards' => [
'customer' => [
'enabled' => 0, // Disable MFA for customer
'forced' => 0,
// ... other parameters
],
'admin' => [
'enabled' => 1, // Enable MFA for admin (default)
'forced' => 0, // Not mandatory
// ... other parameters
],
],Note: After editing the config file, clear the cache:
php artisan config:clear
php artisan cache:clear- Go to MFA management page:
/mfa/setup/customer - Scan QR code with authenticator app (Google Authenticator, Authy, Microsoft Authenticator, etc.)
- Enter 6-digit code from app to verify
- Save recovery codes in a secure place
- Login with username/password as usual
- After successful login, system will require MFA code
- Enter 6-digit code from authenticator app
- Or use 8-character recovery code if device is lost
- View MFA status:
/mfa/manage/customer - View recovery codes:
/mfa/recovery-codes/customer - Regenerate recovery codes: From MFA management page
- Disable MFA: From MFA management page (requires password confirmation)
- Access Admin Panel > Extensions > MFA
- View MFA adoption rate by guard
- See total users and enabled users
- Enable/disable MFA for each guard
- Force users to enable MFA
- Adjust technical parameters
- From MFA management page, admins can reset MFA for any user
- User will need to setup MFA again from scratch
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β User Login Success β
ββββββββββββββββββββββββββ¬βββββββββββββββββββββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββ
β MFA Enabled for β
β this guard? β
ββββββββββ¬ββββββββββββ
β
ββββββββββββββββββ΄βββββββββββββββββ
β No β Yes
βΌ βΌ
βββββββββββββββββ ββββββββββββββββββββββ
β Allow Access β β User enrolled MFA? β
βββββββββββββββββ βββββββββββ¬βββββββββββ
β
ββββββββββββββββββ΄βββββββββββββββββ
β No β Yes
βΌ βΌ
ββββββββββββββββββββ ββββββββββββββββββββ
β MFA Forced? β β Session verified?β
ββββββββββ¬ββββββββββ ββββββββββ¬ββββββββββ
β β
βββββββββββββββ΄βββββββββββ βββββββββββ΄ββββββββββ
β No β Yes β β No β Yes β
βΌ βΌ β βΌ βΌ β
Allow Access Redirect β Redirect Allow Access β
to Setup β to Verify β
β β β β
βΌ β βΌ β
βββββββββββββββ β βββββββββββββββββββ β
β Show QR Codeβ β β Enter 6-digit β β
β & Secret β β β code or β β
ββββββββ¬βββββββ β β recovery code β β
β β ββββββββββ¬βββββββββ β
βΌ β β β
βββββββββββββββ β βΌ β
β Verify Code β β βββββββββββββββββββ β
ββββββββ¬βββββββ β β Code Valid? β β
β β ββββββββββ¬βββββββββ β
βΌ β β β
βββββββββββββββββββ β ββββββββββ΄βββββββββ β
β Generate β β β No β Yes β β
β Recovery Codes β β βΌ βΌ β β
ββββββββββ¬βββββββββ β Error Set β β
β β Session β β
βΌ β Verified β β
βββββββββββββββββββ β β β β
β Show & Save β β βΌ β β
β Recovery Codes β β ββββββββββββββββ β β
ββββββββββ¬βββββββββ β βAllow Access β β β
β β ββββββββββββββββ β β
βΌ β β β
βββββββββββββββββββ β β β
β MFA Activated β β β β
ββββββββββ¬βββββββββ β β β
β β β β
ββββββββββββ΄βββββββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββ
βββββββββββββββββββββββ
β User Login β
β (Email + Password) β
ββββββββββββ¬βββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β Credentials Valid? β
ββββββββββββ¬ββββββββββββ
β
ββββββββ΄βββββββ
β No β Yes β
βΌ βΌ β
Error Check β
MFA β
β β
βΌ β
βββββββββββββββββββββββ
β User enrolled MFA? β
ββββββββββββ¬βββββββββββ
β
ββββββββ΄βββββββ
β No β Yes β
βΌ βΌ β
Allow Redirect β
Access to MFA β
Verify β
β β
βΌ β
ββββββββββββββββββββββββββββββ
β MFA Verification Page β
β β
β [Enter 6-digit code] β
β or β
β [Use recovery code] β
ββββββββββββ¬ββββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β Verify Code β
β (TOTP or Recovery) β
ββββββββββββ¬ββββββββββββ
β
ββββββββ΄βββββββββββ
β Valid β Invalid β
βΌ βΌ β
βββββββββββββββ βββββββββββ
β Set Session β β Show β
β Verified β β Error β
ββββββββ¬βββββββ ββββββ¬βββββ
β β
βΌ βΌ
ββββββββββββββββ ββββββββββββ
β Allow Access β β Try Againβ
ββββββββββββββββ ββββββββββββ
ββββββββββββββββββββββββ
β User lost device β
ββββββββββββ¬ββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β Login Page β
β Enter credentials β
ββββββββββββ¬ββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββ
β MFA Verification Page β
β β
β Click "Use recovery code"β
ββββββββββββ¬ββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββββββ
β Enter 8-char recovery β
β code (e.g. ABCD1234) β
ββββββββββββ¬ββββββββββββββββ
β
βΌ
ββββββββββββββββββββββββ
β Check recovery code β
β in database β
ββββββββββββ¬ββββββββββββ
β
ββββββββ΄ββββββββ
β ValidβInvalidβ
βΌ βΌ β
ββββββββββββββ ββββββββββ
β Mark code β β Error β
β as used β ββββββββββ
βββββββ¬βββββββ β
β β
βΌ β
ββββββββββββββ β
β Login OK β β
βββββββ¬βββββββ β
β β
βΌ β
ββββββββββββββββββββ
β Redirect to β
β MFA Setup β
β (Setup new device)β
ββββββββββββββββββββ
ββββββββββββββββββββββββββββ
β Request to protected β
β route with mfa.verify β
βββββββββββββ¬βββββββββββββββ
β
βΌ
βββββββββββββββββββββββββββββ
β Middleware: Check Auth β
βββββββββββββ¬ββββββββββββββββ
β
ββββββββ΄βββββββ
β Not β Auth β
β Auth β β
βΌ βΌ β
Redirect Check β
to Login MFA β
β β
βΌ β
βββββββββββββββββββββββββββ
β MFA enabled for guard? β
βββββββββββββ¬ββββββββββββββ
β
ββββββββ΄βββββββ
β No β Yes β
βΌ βΌ β
Allow Check β
Access Session β
β β
βΌ β
ββββββββββββββββββββββββββββ
β Session verified? β
βββββββββββββ¬βββββββββββββββ
β
ββββββββ΄βββββββ
β Yes β No β
βΌ βΌ β
Allow Check β
Access User β
MFA β
β β
βΌ β
ββββββββββββββββββββββββββββ
β User enrolled MFA? β
βββββββββββββ¬βββββββββββββββ
β
ββββββββ΄βββββββ
β No β Yes β
βΌ βΌ β
Check Redirect β
Forced to MFA β
MFA Verify β
β β
βΌ β
ββββββββββββββββ β
β MFA Forced? β β
ββββββββ¬ββββββββ β
β β
ββββββ΄βββββ β
βNo βYes β β
βΌ βΌ β β
Allow Redirect β
Access to Setup β
β β
βββββββββββββ
Use mfa.verify middleware to protect routes:
// In routes/web.php
Route::group(['middleware' => ['auth:customer', 'mfa.verify:customer']], function () {
Route::get('/dashboard', 'DashboardController@index');
Route::get('/profile', 'ProfileController@index');
});
// For admin
Route::group(['middleware' => ['auth:admin', 'mfa.verify:admin']], function () {
Route::get('/admin/dashboard', 'AdminController@index');
});// Check if MFA is enabled for guard
if (mfa_is_enabled_for_guard('customer')) {
// MFA is enabled
}
// Check if user has enrolled MFA
if (mfa_is_user_enrolled($user, 'customer')) {
// User has enrolled MFA
}
// Check if session is MFA verified
if (mfa_is_verified()) {
// Session is verified
}
// Mark session as verified
mfa_set_verified();
// Clear verification from session
mfa_clear_verified();app/GP247/Plugins/MFA/
βββ Admin/
β βββ AdminController.php # Admin panel controller
βββ Controllers/
β βββ MFAController.php # Main MFA controller
βββ Helpers/
β βββ TwoFactorHelper.php # Google 2FA helper
βββ Lang/
β βββ en/
β β βββ lang.php # English translations
β βββ vi/
β βββ lang.php # Vietnamese translations
βββ Middleware/
β βββ TwoFactorAuthentication.php # MFA verification middleware
βββ Models/
β βββ ExtensionModel.php # Install/uninstall model
β βββ TwoFactorAuth.php # MFA storage model
βββ Views/
β βββ Admin.blade.php # Admin view
β βββ Frontend/
β βββ setup.blade.php # MFA setup view
β βββ verify.blade.php # MFA verification view
β βββ recovery_codes.blade.php # Recovery codes view
β βββ manage.blade.php # MFA management view
βββ AppConfig.php # Plugin configuration
βββ config.php # Config file
βββ function.php # Helper functions
βββ gp247.json # Plugin metadata
βββ Provider.php # Service provider
βββ Route.php # Routes
βββ readme.md # This documentation
- Secret keys are encrypted in database using Laravel Encryption
- Recovery codes are encrypted in database
- All sensitive data is protected
- Force MFA for Admins: Enable "Forced" for admin guard
- User Education: Guide users to store recovery codes safely
- Regular Monitoring: Track MFA adoption rates
- Backups: Ensure database is regularly backed up
- HTTPS: Require HTTPS for all MFA pages
The plugin supports all TOTP authenticator apps:
- Google Authenticator (iOS, Android)
- Microsoft Authenticator (iOS, Android)
- Authy (iOS, Android, Desktop)
- 1Password (iOS, Android, Desktop)
- LastPass Authenticator
- Duo Mobile
- FreeOTP
- And many other TOTP apps
- User uses recovery code to login
- After login, setup MFA again with new device
- Save new recovery codes
- Check if device time is accurate
- Increase "Window" value in configuration (recommended 1-2)
- Ensure correct QR code was scanned
- Access Admin Panel > Extensions > MFA
- Find user in list
- Click "Reset MFA"
- User will need to setup MFA again
- Website: https://GP247.net
- Email: support@gp247.net
- Documentation: https://gp247.net/en/product/plugin-mfa.html
MIT License
GP247 Team
- Initial release
- Support for Customer, Admin, Vendor, PMO guards
- TOTP authentication with Google Authenticator
- Recovery codes system
- Admin management panel
- Multi-language support (Vietnamese, English)


