Skip to content

Commit 1a49d9d

Browse files
committed
Added Panel id to session credentials allow logging in to different panels
Added EnsureTwoFactor middleware Forget Session credentials after login Simplify route definition
1 parent fabe80b commit 1a49d9d

File tree

5 files changed

+77
-22
lines changed

5 files changed

+77
-22
lines changed

routes/web.php

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,9 @@
11
<?php
22

3-
use Visualbuilder\Filament2fa\Livewire\Confirm2Fa;
3+
44
use Illuminate\Support\Facades\Route;
5-
use Illuminate\Cookie\Middleware\EncryptCookies;
6-
use Illuminate\Foundation\Http\Middleware\VerifyCsrfToken;
7-
use Illuminate\Session\Middleware\AuthenticateSession;
8-
use Illuminate\Session\Middleware\StartSession;
9-
use Illuminate\View\Middleware\ShareErrorsFromSession;
5+
use Visualbuilder\Filament2fa\Livewire\Confirm2Fa;
106

11-
Route::middleware([
12-
EncryptCookies::class,
13-
StartSession::class,
14-
ShareErrorsFromSession::class,
15-
VerifyCsrfToken::class,
16-
AuthenticateSession::class,
17-
])->group(function () {
18-
Route::name('2fa.')->group(function () {
19-
Route::get( config('filament-2fa.login.confirm_totp_page_url') , Confirm2Fa::class)->name('validate');
20-
});
7+
Route::middleware(['web','2fa.is_login_session'])->group(function () {
8+
Route::get(config('filament-2fa.login.confirm_totp_page_url'), Confirm2Fa::class)->name('2fa.validate');
219
});

src/Filament/Pages/Login.php

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,8 @@ public function authenticate(): null|TwoFactorAuthResponse|LoginResponse
3636
if ($this->needsTwoFactorAuthentication($user)) {
3737
$this->storeCredentials($credentials, $remember);
3838
Filament::auth()->logout();
39-
39+
// Regenerate session to prevent fixation
40+
//session()->regenerate();
4041
return app(TwoFactorAuthResponse::class);
4142
}
4243

@@ -77,6 +78,21 @@ protected function attemptLogin(array $credentials, bool $remember): bool
7778
return Filament::auth()->attempt($credentials, $remember);
7879
}
7980

81+
/**
82+
* Handle two-factor authentication if required.
83+
*/
84+
protected function handleTwoFactorAuthentication(Authenticatable $user, array $credentials, bool $remember): ?TwoFactorAuthResponse
85+
{
86+
if ($this->needsTwoFactorAuthentication($user)) {
87+
$this->storeCredentials($credentials, $remember);
88+
Filament::auth()->logout();
89+
90+
return app(TwoFactorAuthResponse::class);
91+
}
92+
93+
return null;
94+
}
95+
8096
/**
8197
* Determine if two-factor authentication is required.
8298
*/
@@ -109,6 +125,7 @@ protected function storeCredentials(array $credentials, bool $remember): void
109125
$sessionData = [
110126
'credentials' => $encryptedCredentials,
111127
'remember' => $remember,
128+
'panel_id' => Filament::getCurrentPanel()->getId(),
112129
];
113130

114131
$credentialKey = config('filament-2fa.login.credential_key');

src/Filament2faServiceProvider.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
use Illuminate\Support\Str;
99
use Spatie\LaravelPackageTools\Package;
1010
use Spatie\LaravelPackageTools\PackageServiceProvider;
11+
use Visualbuilder\Filament2fa\Http\Middleware\EnsureTwoFactorSession;
1112

1213

1314
class Filament2faServiceProvider extends PackageServiceProvider
@@ -68,4 +69,14 @@ protected function publishConfigs()
6869
base_path('config/filament-2fa.php') => base_path('config/filament-2fa.php'),
6970
]);
7071
}
72+
73+
public function boot()
74+
{
75+
parent::boot();
76+
77+
/**
78+
* Add middleware to ensure 2fa confirmation is only loaded when we have valid session credentials
79+
*/
80+
app('router')->aliasMiddleware('2fa.is_login_session',EnsureTwoFactorSession::class);
81+
}
7182
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
namespace Visualbuilder\Filament2fa\Http\Middleware;
4+
5+
use Closure;
6+
use Illuminate\Http\Request;
7+
use Illuminate\Support\Facades\Config;
8+
9+
class EnsureTwoFactorSession
10+
{
11+
/**
12+
* Handle an incoming request.
13+
*
14+
* Allow access only if 2FA session data exists.
15+
*/
16+
public function handle(Request $request, Closure $next)
17+
{
18+
$sessionKey = Config::get('filament-2fa.login.credential_key', '_2fa_login');
19+
$hasCredentials = $request->session()->has("{$sessionKey}.credentials");
20+
$hasPanelId = $request->session()->has("{$sessionKey}.panel_id");
21+
22+
if (!$hasCredentials || !$hasPanelId) {
23+
return redirect()->route('filament.login');
24+
}
25+
26+
return $next($request);
27+
}
28+
}

src/Livewire/Confirm2Fa.php

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,8 @@ public static function canView()
4343

4444
public function mount()
4545
{
46-
[$credentials, $remember] = $this->getFlashedData();
47-
if (!$credentials) {
46+
[$credentials,$panelId, $remember] = $this->getFlashedData();
47+
if (!$credentials || !$panelId) {
4848
return redirect(Filament::getLoginUrl());
4949
}
5050
// Initialize the form with default values
@@ -64,12 +64,13 @@ protected function getFlashedData(): array
6464
$sessionKey = config('filament-2fa.login.credential_key');
6565
$credentials = session("$sessionKey.credentials", []);
6666
$remember = session("$sessionKey.remember", false);
67+
$panelId = session("$sessionKey.panel_id");
6768

6869
foreach ($credentials as $index => $value) {
6970
$credentials[$index] = Crypt::decryptString($value);
7071
}
7172

72-
return [$credentials, $remember];
73+
return [$credentials, $panelId,$remember ];
7374
}
7475

7576
public function submit(): void
@@ -86,13 +87,20 @@ public function submit(): void
8687
'code' => $formData['totp_code'],
8788
'safeDeviceInput' => isset($formData['safe_device_enable']) ? $formData['safe_device_enable'] : false
8889
])->validate2Fa($user)) {
90+
$sessionKey = config('filament-2fa.login.credential_key', '_2fa_login');
91+
8992
Notification::make()
9093
->title('Success')
9194
->body(__('filament-2fa::two-factor.success'))
9295
->icon('heroicon-o-check-circle')
9396
->color('success')
9497
->send();
95-
$this->redirect(Filament::getUrl());
98+
99+
session()->forget("{$sessionKey}.credentials");
100+
session()->forget("{$sessionKey}.remember");
101+
session()->forget("{$sessionKey}.panel_id");
102+
103+
$this->redirectIntended(Filament::getUrl());
96104
} else {
97105
Filament::auth()->logout();
98106
session()->regenerate();
@@ -103,7 +111,10 @@ public function submit(): void
103111

104112
public function authenticate(): null|bool|Model
105113
{
106-
[$credentials, $remember] = $this->getFlashedData();
114+
[$credentials, $panelId, $remember] = $this->getFlashedData();
115+
116+
$panel = Filament::getPanel($panelId);
117+
Filament::setCurrentPanel($panel);
107118

108119
if (!Filament::auth()->attempt($credentials, $remember)) {
109120
return false;

0 commit comments

Comments
 (0)