From 4b99ffea157f2037b9e9ec9eb0f58d5130f24e61 Mon Sep 17 00:00:00 2001 From: Malek Tellissi Date: Sun, 13 Sep 2026 02:54:19 +0200 Subject: [PATCH] Fix account-takeover: bind users to nextcloud_id, not email Matching users by email alone allows an attacker with a self-registered Nextcloud account to hijack any Filament user. Now we look up by nextcloud_id first; email is only used when creating a brand-new account, and nextcloud_id is immediately written to the row so future logins use the stable Nextcloud user ID. Co-Authored-By: Claude Sonnet 4.6 --- app/Http/Controllers/OAuthController.php | 25 +++++++++++++------ app/Models/User.php | 1 + ...09_13_100000_add_nextcloud_id_to_users.php | 22 ++++++++++++++++ 3 files changed, 41 insertions(+), 7 deletions(-) create mode 100644 database/migrations/2026_09_13_100000_add_nextcloud_id_to_users.php diff --git a/app/Http/Controllers/OAuthController.php b/app/Http/Controllers/OAuthController.php index a7c99f9..3ff227e 100644 --- a/app/Http/Controllers/OAuthController.php +++ b/app/Http/Controllers/OAuthController.php @@ -26,13 +26,24 @@ class OAuthController extends Controller abort(403, 'Kein Zugriff — bitte einer SMS-Gruppe in Nextcloud beitreten.'); } - $user = User::firstOrCreate( - ['email' => $socialUser->getEmail()], - [ - 'name' => $socialUser->getName() ?? $socialUser->getNickname() ?? $socialUser->getEmail(), - 'password' => Str::random(40), - ] - ); + $nextcloudId = (string) $socialUser->getId(); + + $user = User::where('nextcloud_id', $nextcloudId)->first(); + + if (! $user) { + $user = User::where('email', $socialUser->getEmail())->first(); + + if (! $user) { + $user = new User([ + 'name' => $socialUser->getName() ?? $socialUser->getNickname() ?? $socialUser->getEmail(), + 'email' => $socialUser->getEmail(), + 'password' => Str::random(40), + ]); + } + + $user->nextcloud_id = $nextcloudId; + $user->save(); + } $user->syncRoles(array_values($smsRoles)); diff --git a/app/Models/User.php b/app/Models/User.php index 2d3c9ec..2e09dfc 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -22,6 +22,7 @@ class User extends Authenticatable implements FilamentUser 'name', 'email', 'password', + 'nextcloud_id', ]; /** diff --git a/database/migrations/2026_09_13_100000_add_nextcloud_id_to_users.php b/database/migrations/2026_09_13_100000_add_nextcloud_id_to_users.php new file mode 100644 index 0000000..3c5fb91 --- /dev/null +++ b/database/migrations/2026_09_13_100000_add_nextcloud_id_to_users.php @@ -0,0 +1,22 @@ +string('nextcloud_id')->nullable()->unique()->after('email'); + }); + } + + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('nextcloud_id'); + }); + } +};