Make sure 2fa requirement is enforced (#1289)

This commit is contained in:
Boy132 2025-04-23 16:03:10 +02:00 committed by GitHub
parent 914e215bc0
commit 544aaab960
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 29 additions and 14 deletions

View File

@ -5,6 +5,9 @@ namespace App\Http\Middleware;
use Illuminate\Support\Str; use Illuminate\Support\Str;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use App\Exceptions\Http\TwoFactorAuthRequiredException; use App\Exceptions\Http\TwoFactorAuthRequiredException;
use App\Filament\Pages\Auth\EditProfile;
use App\Livewire\AlertBanner;
use App\Models\User;
class RequireTwoFactorAuthentication class RequireTwoFactorAuthentication
{ {
@ -14,11 +17,6 @@ class RequireTwoFactorAuthentication
public const LEVEL_ALL = 2; public const LEVEL_ALL = 2;
/**
* The route to redirect a user to enable 2FA.
*/
protected string $redirectRoute = '/account';
/** /**
* Check the user state on the incoming request to determine if they should be allowed to * Check the user state on the incoming request to determine if they should be allowed to
* proceed or not. This checks if the Panel is configured to require 2FA on an account in * proceed or not. This checks if the Panel is configured to require 2FA on an account in
@ -29,31 +27,37 @@ class RequireTwoFactorAuthentication
*/ */
public function handle(Request $request, \Closure $next): mixed public function handle(Request $request, \Closure $next): mixed
{ {
/** @var ?User $user */
$user = $request->user(); $user = $request->user();
$uri = rtrim($request->getRequestUri(), '/') . '/'; $uri = rtrim($request->getRequestUri(), '/') . '/';
$current = $request->route()->getName(); $current = $request->route()->getName();
if (!$user || Str::startsWith($uri, ['/auth/']) || Str::startsWith($current, ['auth.', 'account.'])) { if (!$user || Str::startsWith($uri, ['/auth/', '/profile']) || Str::startsWith($current, ['auth.', 'account.', 'filament.app.auth.'])) {
return $next($request); return $next($request);
} }
/** @var \App\Models\User $user */
$level = (int) config('panel.auth.2fa_required'); $level = (int) config('panel.auth.2fa_required');
// If this setting is not configured, or the user is already using 2FA then we can just
// send them right through, nothing else needs to be checked.
//
// If the level is set as admin and the user is not an admin, pass them through as well.
if ($level === self::LEVEL_NONE || $user->use_totp) { if ($level === self::LEVEL_NONE || $user->use_totp) {
// If this setting is not configured, or the user is already using 2FA then we can just send them right through, nothing else needs to be checked.
return $next($request); return $next($request);
} elseif ($level === self::LEVEL_ADMIN && !$user->isRootAdmin()) { } elseif ($level === self::LEVEL_ADMIN && !$user->isAdmin()) {
// If the level is set as admin and the user is not an admin, pass them through as well.
return $next($request); return $next($request);
} }
// For API calls return an exception which gets rendered nicely in the API response. // For API calls return an exception which gets rendered nicely in the API response...
if ($request->isJson() || Str::startsWith($uri, '/api/')) { if ($request->isJson() || Str::startsWith($uri, '/api/')) {
throw new TwoFactorAuthRequiredException(); throw new TwoFactorAuthRequiredException();
} }
return redirect()->to($this->redirectRoute); // ... otherwise display banner and redirect to profile
AlertBanner::make('2fa_must_be_enabled')
->body(trans('auth.2fa_must_be_enabled'))
->warning()
->send();
return redirect(EditProfile::getUrl(['tab' => '-2fa-tab'], panel: 'app'));
} }
} }

View File

@ -5,6 +5,7 @@ namespace App\Providers\Filament;
use App\Filament\Pages\Auth\Login; use App\Filament\Pages\Auth\Login;
use App\Filament\Pages\Auth\EditProfile; use App\Filament\Pages\Auth\EditProfile;
use App\Http\Middleware\LanguageMiddleware; use App\Http\Middleware\LanguageMiddleware;
use App\Http\Middleware\RequireTwoFactorAuthentication;
use Filament\Http\Middleware\Authenticate; use Filament\Http\Middleware\Authenticate;
use Filament\Http\Middleware\DisableBladeIconComponents; use Filament\Http\Middleware\DisableBladeIconComponents;
use Filament\Http\Middleware\DispatchServingFilamentEvent; use Filament\Http\Middleware\DispatchServingFilamentEvent;
@ -72,6 +73,7 @@ class AdminPanelProvider extends PanelProvider
DisableBladeIconComponents::class, DisableBladeIconComponents::class,
DispatchServingFilamentEvent::class, DispatchServingFilamentEvent::class,
LanguageMiddleware::class, LanguageMiddleware::class,
RequireTwoFactorAuthentication::class,
]) ])
->authMiddleware([ ->authMiddleware([
Authenticate::class, Authenticate::class,

View File

@ -4,6 +4,8 @@ namespace App\Providers\Filament;
use App\Filament\Pages\Auth\Login; use App\Filament\Pages\Auth\Login;
use App\Filament\Pages\Auth\EditProfile; use App\Filament\Pages\Auth\EditProfile;
use App\Http\Middleware\LanguageMiddleware;
use App\Http\Middleware\RequireTwoFactorAuthentication;
use Filament\Facades\Filament; use Filament\Facades\Filament;
use Filament\Http\Middleware\Authenticate; use Filament\Http\Middleware\Authenticate;
use Filament\Http\Middleware\DisableBladeIconComponents; use Filament\Http\Middleware\DisableBladeIconComponents;
@ -57,6 +59,8 @@ class AppPanelProvider extends PanelProvider
SubstituteBindings::class, SubstituteBindings::class,
DisableBladeIconComponents::class, DisableBladeIconComponents::class,
DispatchServingFilamentEvent::class, DispatchServingFilamentEvent::class,
LanguageMiddleware::class,
RequireTwoFactorAuthentication::class,
]) ])
->authMiddleware([ ->authMiddleware([
Authenticate::class, Authenticate::class,

View File

@ -7,6 +7,8 @@ use App\Filament\Pages\Auth\Login;
use App\Filament\Admin\Resources\ServerResource\Pages\EditServer; use App\Filament\Admin\Resources\ServerResource\Pages\EditServer;
use App\Filament\Pages\Auth\EditProfile; use App\Filament\Pages\Auth\EditProfile;
use App\Http\Middleware\Activity\ServerSubject; use App\Http\Middleware\Activity\ServerSubject;
use App\Http\Middleware\LanguageMiddleware;
use App\Http\Middleware\RequireTwoFactorAuthentication;
use App\Models\Server; use App\Models\Server;
use Filament\Facades\Filament; use Filament\Facades\Filament;
use Filament\Http\Middleware\Authenticate; use Filament\Http\Middleware\Authenticate;
@ -79,6 +81,8 @@ class ServerPanelProvider extends PanelProvider
SubstituteBindings::class, SubstituteBindings::class,
DisableBladeIconComponents::class, DisableBladeIconComponents::class,
DispatchServingFilamentEvent::class, DispatchServingFilamentEvent::class,
LanguageMiddleware::class,
RequireTwoFactorAuthentication::class,
ServerSubject::class, ServerSubject::class,
]) ])
->authMiddleware([ ->authMiddleware([

View File

@ -18,5 +18,6 @@ return [
'two-factor-code' => 'Two Factor Code', 'two-factor-code' => 'Two Factor Code',
'password' => 'The provided password is incorrect.', 'password' => 'The provided password is incorrect.',
'throttle' => 'Too many login attempts. Please try again in :seconds seconds.', 'throttle' => 'Too many login attempts. Please try again in :seconds seconds.',
'2fa_must_be_enabled' => 'The administrator has required that 2-Factor Authentication must be enabled for your account in order to use the Panel.',
]; ];