diff --git a/app/Http/Middleware/RequireTwoFactorAuthentication.php b/app/Http/Middleware/RequireTwoFactorAuthentication.php index 3a098c5bd..5bb02d128 100644 --- a/app/Http/Middleware/RequireTwoFactorAuthentication.php +++ b/app/Http/Middleware/RequireTwoFactorAuthentication.php @@ -5,6 +5,9 @@ namespace App\Http\Middleware; use Illuminate\Support\Str; use Illuminate\Http\Request; use App\Exceptions\Http\TwoFactorAuthRequiredException; +use App\Filament\Pages\Auth\EditProfile; +use App\Livewire\AlertBanner; +use App\Models\User; class RequireTwoFactorAuthentication { @@ -14,11 +17,6 @@ class RequireTwoFactorAuthentication 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 * 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 { + /** @var ?User $user */ $user = $request->user(); + $uri = rtrim($request->getRequestUri(), '/') . '/'; $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); } - /** @var \App\Models\User $user */ $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 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); - } 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); } - // 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/')) { 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')); } } diff --git a/app/Providers/Filament/AdminPanelProvider.php b/app/Providers/Filament/AdminPanelProvider.php index 35c03f0d5..83db82839 100644 --- a/app/Providers/Filament/AdminPanelProvider.php +++ b/app/Providers/Filament/AdminPanelProvider.php @@ -5,6 +5,7 @@ namespace App\Providers\Filament; use App\Filament\Pages\Auth\Login; use App\Filament\Pages\Auth\EditProfile; use App\Http\Middleware\LanguageMiddleware; +use App\Http\Middleware\RequireTwoFactorAuthentication; use Filament\Http\Middleware\Authenticate; use Filament\Http\Middleware\DisableBladeIconComponents; use Filament\Http\Middleware\DispatchServingFilamentEvent; @@ -72,6 +73,7 @@ class AdminPanelProvider extends PanelProvider DisableBladeIconComponents::class, DispatchServingFilamentEvent::class, LanguageMiddleware::class, + RequireTwoFactorAuthentication::class, ]) ->authMiddleware([ Authenticate::class, diff --git a/app/Providers/Filament/AppPanelProvider.php b/app/Providers/Filament/AppPanelProvider.php index 44446d157..44ac35ec9 100644 --- a/app/Providers/Filament/AppPanelProvider.php +++ b/app/Providers/Filament/AppPanelProvider.php @@ -4,6 +4,8 @@ namespace App\Providers\Filament; use App\Filament\Pages\Auth\Login; use App\Filament\Pages\Auth\EditProfile; +use App\Http\Middleware\LanguageMiddleware; +use App\Http\Middleware\RequireTwoFactorAuthentication; use Filament\Facades\Filament; use Filament\Http\Middleware\Authenticate; use Filament\Http\Middleware\DisableBladeIconComponents; @@ -57,6 +59,8 @@ class AppPanelProvider extends PanelProvider SubstituteBindings::class, DisableBladeIconComponents::class, DispatchServingFilamentEvent::class, + LanguageMiddleware::class, + RequireTwoFactorAuthentication::class, ]) ->authMiddleware([ Authenticate::class, diff --git a/app/Providers/Filament/ServerPanelProvider.php b/app/Providers/Filament/ServerPanelProvider.php index 6a4051da5..d047c80b8 100644 --- a/app/Providers/Filament/ServerPanelProvider.php +++ b/app/Providers/Filament/ServerPanelProvider.php @@ -7,6 +7,8 @@ use App\Filament\Pages\Auth\Login; use App\Filament\Admin\Resources\ServerResource\Pages\EditServer; use App\Filament\Pages\Auth\EditProfile; use App\Http\Middleware\Activity\ServerSubject; +use App\Http\Middleware\LanguageMiddleware; +use App\Http\Middleware\RequireTwoFactorAuthentication; use App\Models\Server; use Filament\Facades\Filament; use Filament\Http\Middleware\Authenticate; @@ -79,6 +81,8 @@ class ServerPanelProvider extends PanelProvider SubstituteBindings::class, DisableBladeIconComponents::class, DispatchServingFilamentEvent::class, + LanguageMiddleware::class, + RequireTwoFactorAuthentication::class, ServerSubject::class, ]) ->authMiddleware([ diff --git a/lang/en/auth.php b/lang/en/auth.php index d8fb89a75..b995376f7 100644 --- a/lang/en/auth.php +++ b/lang/en/auth.php @@ -18,5 +18,6 @@ return [ 'two-factor-code' => 'Two Factor Code', 'password' => 'The provided password is incorrect.', '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.', ];