From 6840624be2ed8850b4a34b611965e617b1496361 Mon Sep 17 00:00:00 2001 From: Alexander Gabriel Date: Mon, 10 Nov 2025 19:29:35 +0000 Subject: [PATCH] Login Logic --- config/filament-oauth2.php | 16 +++ config/oauth2.php | 6 - .../migrations/create_oauth2_table.php.stub | 19 --- routes/web.php | 26 ++++ src/FilamentOauth2.php | 10 +- src/FilamentOauth2Plugin.php | 3 +- src/FilamentOauth2ServiceProvider.php | 71 +-------- src/Http/Controllers/Oauth2Controller.php | 136 ++++++++++++++++++ 8 files changed, 191 insertions(+), 96 deletions(-) create mode 100644 config/filament-oauth2.php delete mode 100644 config/oauth2.php delete mode 100644 database/migrations/create_oauth2_table.php.stub create mode 100644 routes/web.php create mode 100644 src/Http/Controllers/Oauth2Controller.php diff --git a/config/filament-oauth2.php b/config/filament-oauth2.php new file mode 100644 index 0000000..b3c04b5 --- /dev/null +++ b/config/filament-oauth2.php @@ -0,0 +1,16 @@ + env("OAUTH2_CLIENT_ID"), + 'clientSecret' => env("OAUTH2_CLIENT_SECRET"), + 'baseUrl' => env("OAUTH2_BASE_URL"), // https://DOMAIN/realms/REALM/protocol/openid-connect + 'urlAuthorize' => env("OAUTH2_URL_AUTHORIZE", env("OAUTH2_BASE_URL")."/auth"), + 'urlAccessToken' => env("OAUTH2_URL_ACCESS_TOKEN", env("OAUTH2_BASE_URL")."/token"), + 'urlResourceOwnerDetails' => env("OAUTH2_URL_RSOURCE_OWNER_DETAILS", env("OAUTH2_BASE_URL")."/userinfo"), + 'scopes' => env("OAUTH2_SCOPES", "profile email openid"), + 'updateRoles' => env("OAUTH2_UPDATE_ROLES", false) + +]; diff --git a/config/oauth2.php b/config/oauth2.php deleted file mode 100644 index 7a338d3..0000000 --- a/config/oauth2.php +++ /dev/null @@ -1,6 +0,0 @@ -id(); - - // add fields - - $table->timestamps(); - }); - } -}; diff --git a/routes/web.php b/routes/web.php new file mode 100644 index 0000000..d79883e --- /dev/null +++ b/routes/web.php @@ -0,0 +1,26 @@ +getPath()) + ->middleware($panel->getMiddleware()) + ->group(function () { + Route::get('login', [Oauth2Controller::class, 'redirectToOauth2Server'])->name('redirectToOauth2Server'); + Route::name('filament-oauth2.') + ->prefix('filament-oauth2') + ->group(function () { + Route::get('redirectToOauth2Server', [Oauth2Controller::class, 'redirectToOauth2Server']) + ->name('redirectToOauth2Server'); + Route::get('handleCallback', [Oauth2Controller::class, 'handleCallback']) + ->name('handleCallback'); + }); + + }); + + diff --git a/src/FilamentOauth2.php b/src/FilamentOauth2.php index 9b0199d..69d9c44 100644 --- a/src/FilamentOauth2.php +++ b/src/FilamentOauth2.php @@ -2,4 +2,12 @@ namespace AlexanderGabriel\FilamentOauth2; -class FilamentOauth2 {} +use AlexanderGabriel\FilamentOauth2\Http\Controllers\Oauth2Controller; + +class FilamentOauth2 { + + public static function getLoginRouteAction(): array + { + return [Oauth2Controller::class, 'redirectToOauth2Server']; + } +} diff --git a/src/FilamentOauth2Plugin.php b/src/FilamentOauth2Plugin.php index e081b22..606bdca 100644 --- a/src/FilamentOauth2Plugin.php +++ b/src/FilamentOauth2Plugin.php @@ -2,6 +2,7 @@ namespace AlexanderGabriel\FilamentOauth2; +use AlexanderGabriel\FilamentOauth2\Facades\FilamentOauth2; use Filament\Contracts\Plugin; use Filament\Panel; @@ -14,7 +15,7 @@ class FilamentOauth2Plugin implements Plugin public function register(Panel $panel): void { - // + $panel->login(FilamentOauth2::getLoginRouteAction()); } public function boot(Panel $panel): void diff --git a/src/FilamentOauth2ServiceProvider.php b/src/FilamentOauth2ServiceProvider.php index 5920479..7a296b1 100644 --- a/src/FilamentOauth2ServiceProvider.php +++ b/src/FilamentOauth2ServiceProvider.php @@ -2,12 +2,6 @@ namespace AlexanderGabriel\FilamentOauth2; -use Filament\Support\Assets\AlpineComponent; -use Filament\Support\Assets\Asset; -use Filament\Support\Assets\Css; -use Filament\Support\Assets\Js; -use Filament\Support\Facades\FilamentAsset; -use Filament\Support\Facades\FilamentIcon; use Illuminate\Filesystem\Filesystem; use Livewire\Features\SupportTesting\Testable; use Spatie\LaravelPackageTools\Commands\InstallCommand; @@ -34,10 +28,9 @@ class FilamentOauth2ServiceProvider extends PackageServiceProvider ->hasInstallCommand(function (InstallCommand $command) { $command ->publishConfigFile() - ->publishMigrations() - ->askToRunMigrations() ->askToStarRepoOnGitHub('alexandergabriel/filament-oauth2'); - }); + }) + ->hasRoutes('web'); $configFileName = $package->shortName(); @@ -45,10 +38,6 @@ class FilamentOauth2ServiceProvider extends PackageServiceProvider $package->hasConfigFile(); } - if (file_exists($package->basePath('/../database/migrations'))) { - $package->hasMigrations($this->getMigrations()); - } - if (file_exists($package->basePath('/../resources/lang'))) { $package->hasTranslations(); } @@ -62,20 +51,6 @@ class FilamentOauth2ServiceProvider extends PackageServiceProvider public function packageBooted(): void { - // Asset Registration - FilamentAsset::register( - $this->getAssets(), - $this->getAssetPackageName() - ); - - FilamentAsset::registerScriptData( - $this->getScriptData(), - $this->getAssetPackageName() - ); - - // Icon Registration - FilamentIcon::register($this->getIcons()); - // Handle Stubs if (app()->runningInConsole()) { foreach (app(Filesystem::class)->files(__DIR__ . '/../stubs/') as $file) { @@ -89,23 +64,6 @@ class FilamentOauth2ServiceProvider extends PackageServiceProvider Testable::mixin(new TestsFilamentOauth2); } - protected function getAssetPackageName(): ?string - { - return 'alexandergabriel/filament-oauth2'; - } - - /** - * @return array - */ - protected function getAssets(): array - { - return [ - // AlpineComponent::make('filament-oauth2', __DIR__ . '/../resources/dist/components/filament-oauth2.js'), - Css::make('filament-oauth2-styles', __DIR__ . '/../resources/dist/filament-oauth2.css'), - Js::make('filament-oauth2-scripts', __DIR__ . '/../resources/dist/filament-oauth2.js'), - ]; - } - /** * @return array */ @@ -116,14 +74,6 @@ class FilamentOauth2ServiceProvider extends PackageServiceProvider ]; } - /** - * @return array - */ - protected function getIcons(): array - { - return []; - } - /** * @return array */ @@ -132,21 +82,4 @@ class FilamentOauth2ServiceProvider extends PackageServiceProvider return []; } - /** - * @return array - */ - protected function getScriptData(): array - { - return []; - } - - /** - * @return array - */ - protected function getMigrations(): array - { - return [ - 'create_filament-oauth2_table', - ]; - } } diff --git a/src/Http/Controllers/Oauth2Controller.php b/src/Http/Controllers/Oauth2Controller.php new file mode 100644 index 0000000..35f765c --- /dev/null +++ b/src/Http/Controllers/Oauth2Controller.php @@ -0,0 +1,136 @@ +oauth2Provider = new GenericProvider([ + 'clientId' => config('filament-oauth2.clientId'), // The client ID assigned to you by the provider + 'clientSecret' => config('filament-oauth2.clientSecret'), // The client password assigned to you by the provider + 'redirectUri' => route('filament-oauth2.handleCallback'), + 'urlAuthorize' => config('filament-oauth2.urlAuthorize'), + 'urlAccessToken' => config('filament-oauth2.urlAccessToken'), + 'urlResourceOwnerDetails' => config('filament-oauth2.urlResourceOwnerDetails'), + 'scopes' => config('filament-oauth2.scopes'), + ]); + } + + public function redirectToOauth2Server() + { + return redirect($this->oauth2Provider->getAuthorizationUrl()); + } + + public function handleCallback(Request $request) + { + try { + $accessToken = $this->oauth2Provider->getAccessToken('authorization_code', ['code' => $request->input('code')]); + $oauth2User = $this->oauth2Provider->getResourceOwner($accessToken)->toArray(); + + $user = User::firstOrCreate([ + 'email' => $oauth2User['email'], + ],[ + 'name' => $oauth2User['name'], + 'password' => 'nonsense' + ]); + if($user->name != $oauth2User['name']) + { + $user->name = $oauth2User['name']; + $user->save(); + } + + Filament::auth()->loginUsingId($user->id, false); + + if ( + ($user instanceof FilamentUser) && + (! $user->canAccessPanel(Filament::getCurrentPanel())) + ) { + Filament::auth()->logout(); + + $this->throwFailureValidationException(); + } + + session()->regenerate(); + + //Should i update Roles and are there roles? + $hasRoles = false; + try { + $roles = $user->roles(); + if($roles) $hasRoles = true; + } + catch (Exception $e) { + //keine Rollen... Nichts tun... + } + if($hasRoles && config('filament-oauth2.updateRoles') != false) { + //Are there roles in the Token? + $accessToken = explode(".", $accessToken); + if(isset($accessToken[1])) { + $accessToken = json_decode(base64_decode($accessToken[1])); + $clientId = config('filament-oauth2.clientId'); + if(isset($accessToken->resource_access) && isset($accessToken->resource_access->$clientId)) { + // Roles are defined. Maybe empty to remove all Roles from user + // TODO: test + if(!isset($accessToken->resource_access->$clientId->roles)) $roles = []; + else $roles = $accessToken->resource_access->$clientId->roles; + + $userRoles = $user->roles(); + + //disconnect roles + foreach ($userRoles as $userRole) { + if(!in_array($userRole, $roles)) { + $user->roles()->detach($userRole); + } + } + + // connect or create roles + foreach($roles as $role) { + $existingRole = Role::first('name', '=', $role); + if($existingRole) { + $user->roles()->attach($existingRole->id); + } else { + $newRole = Role::create(['name' => $role]); + $newRole->save(); + $user->roles()->attach($newRole); + } + } + + } + } + } + + return app(LoginResponse::class); + + } catch (IdentityProviderException $e) { + dd($e->getMessage()); + } + } + + protected function throwFailureValidationException(): never + { + throw ValidationException::withMessages([ + 'data.email' => __('filament-panels::pages/auth/login.messages.failed'), + ]); + } + + //TODO: Logout + // filament-oauth2-demo/vendor/filament/filament/src/Http/Controllers/Auth/LogoutController.php + + +} \ No newline at end of file