From c2c9464133948dac6801008edde389806c7c4642 Mon Sep 17 00:00:00 2001 From: Russ Long Date: Sun, 26 Apr 2026 16:32:53 -0400 Subject: [PATCH 1/2] Implement OIDC authentication via Laravel Socialite --- .env.example | 6 + .../Controllers/Auth/SocialiteController.php | 58 +++ app/Providers/EventServiceProvider.php | 3 + app/Providers/Filament/AdminPanelProvider.php | 22 + app/User.php | 2 +- composer.json | 5 +- composer.lock | 466 +++++++++++++++++- config/services.php | 7 + ...22_add_socialite_fields_to_users_table.php | 31 ++ resources/views/auth/login.blade.php | 4 + routes/web.php | 4 + 11 files changed, 605 insertions(+), 3 deletions(-) create mode 100644 app/Http/Controllers/Auth/SocialiteController.php create mode 100644 database/migrations/2026_04_26_162522_add_socialite_fields_to_users_table.php diff --git a/.env.example b/.env.example index 925b0ae..8222755 100644 --- a/.env.example +++ b/.env.example @@ -33,3 +33,9 @@ MAIL_FROM_NAME=null PUSHER_APP_ID= PUSHER_APP_KEY= PUSHER_APP_SECRET= + +OIDC_BASE_URL= +OIDC_CLIENT_ID= +OIDC_CLIENT_SECRET= +OIDC_REDIRECT_URI="${APP_URL}/auth/social/oidc/callback" + diff --git a/app/Http/Controllers/Auth/SocialiteController.php b/app/Http/Controllers/Auth/SocialiteController.php new file mode 100644 index 0000000..feb9817 --- /dev/null +++ b/app/Http/Controllers/Auth/SocialiteController.php @@ -0,0 +1,58 @@ +redirect(); + } + + public function handleProviderCallback($provider) + { + try { + $socialUser = Socialite::driver($provider)->user(); + } catch (\Exception $e) { + return redirect('/login')->with('error', 'Authentication failed.'); + } + + // Find user by provider_id + $user = User::where('provider_name', $provider) + ->where('provider_id', $socialUser->getId()) + ->first(); + + if (!$user) { + // Find user by email to link + $user = User::where('email', $socialUser->getEmail())->first(); + + if ($user) { + // Link the account + $user->update([ + 'provider_name' => $provider, + 'provider_id' => $socialUser->getId(), + ]); + } else { + // Optionally create a new user + $user = User::create([ + 'name' => $socialUser->getName() ?? $socialUser->getNickname() ?? $socialUser->getEmail(), + 'email' => $socialUser->getEmail(), + 'provider_name' => $provider, + 'provider_id' => $socialUser->getId(), + 'password' => bcrypt(Str::random(24)), + ]); + } + } + + Auth::login($user); + + return redirect()->intended('/admin'); // Redirect to filament admin or home + } +} diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index fca6152..9958058 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -16,6 +16,9 @@ class EventServiceProvider extends ServiceProvider 'App\Events\Event' => [ 'App\Listeners\EventListener', ], + \SocialiteProviders\Manager\SocialiteWasCalled::class => [ + \SocialiteProviders\OIDC\OIDCExtendSocialite::class.'@handle', + ], ]; /** diff --git a/app/Providers/Filament/AdminPanelProvider.php b/app/Providers/Filament/AdminPanelProvider.php index 0795141..1038366 100644 --- a/app/Providers/Filament/AdminPanelProvider.php +++ b/app/Providers/Filament/AdminPanelProvider.php @@ -18,8 +18,30 @@ use Illuminate\Routing\Middleware\SubstituteBindings; use Illuminate\Session\Middleware\StartSession; use Illuminate\View\Middleware\ShareErrorsFromSession; +use Filament\Support\Facades\FilamentView; +use Illuminate\Support\Facades\Blade; + class AdminPanelProvider extends PanelProvider { + public function boot() + { + FilamentView::registerRenderHook( + 'panels::auth.login.form.after', + fn (): string => Blade::render(' +
+ + Login with OIDC + +
+ '), + ); + } + public function panel(Panel $panel): Panel { return $panel diff --git a/app/User.php b/app/User.php index 4fb71b1..60cfd42 100644 --- a/app/User.php +++ b/app/User.php @@ -18,7 +18,7 @@ class User extends Authenticatable implements FilamentUser, HasName * @var array */ protected $fillable = [ - 'name', 'email', 'password', + 'name', 'email', 'password', 'provider_name', 'provider_id', ]; /** diff --git a/composer.json b/composer.json index 1cb66dc..7cf9e77 100644 --- a/composer.json +++ b/composer.json @@ -9,9 +9,12 @@ "barryvdh/laravel-snappy": "^1.0", "carlos-meneses/laravel-mpdf": "^2.1", "filament/filament": "^5.0", + "kovah/laravel-socialite-oidc": "^0.7.0", "laravel/framework": "^11.0", + "laravel/socialite": "^5.26", "laravel/tinker": "^2.9", - "laravel/ui": "^4.2" + "laravel/ui": "^4.2", + "socialiteproviders/manager": "^4.9" }, "require-dev": { "barryvdh/laravel-debugbar": "^3.8", diff --git a/composer.lock b/composer.lock index f26ddb5..6de3d70 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "513e167cc5aa3dc9285bd5312b837eca", + "content-hash": "3c08b43425d232f81481839d3c2286fc", "packages": [ { "name": "barryvdh/laravel-snappy", @@ -1545,6 +1545,70 @@ }, "time": "2026-04-03T15:40:06+00:00" }, + { + "name": "firebase/php-jwt", + "version": "v7.0.5", + "source": { + "type": "git", + "url": "https://github.com/googleapis/php-jwt.git", + "reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/googleapis/php-jwt/zipball/47ad26bab5e7c70ae8a6f08ed25ff83631121380", + "reference": "47ad26bab5e7c70ae8a6f08ed25ff83631121380", + "shasum": "" + }, + "require": { + "php": "^8.0" + }, + "require-dev": { + "guzzlehttp/guzzle": "^7.4", + "phpfastcache/phpfastcache": "^9.2", + "phpspec/prophecy-phpunit": "^2.0", + "phpunit/phpunit": "^9.5", + "psr/cache": "^2.0||^3.0", + "psr/http-client": "^1.0", + "psr/http-factory": "^1.0" + }, + "suggest": { + "ext-sodium": "Support EdDSA (Ed25519) signatures", + "paragonie/sodium_compat": "Support EdDSA (Ed25519) signatures when libsodium is not present" + }, + "type": "library", + "autoload": { + "psr-4": { + "Firebase\\JWT\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "BSD-3-Clause" + ], + "authors": [ + { + "name": "Neuman Vong", + "email": "neuman+pear@twilio.com", + "role": "Developer" + }, + { + "name": "Anant Narayanan", + "email": "anant@php.net", + "role": "Developer" + } + ], + "description": "A simple library to encode and decode JSON Web Tokens (JWT) in PHP. Should conform to the current spec.", + "homepage": "https://github.com/firebase/php-jwt", + "keywords": [ + "jwt", + "php" + ], + "support": { + "issues": "https://github.com/googleapis/php-jwt/issues", + "source": "https://github.com/googleapis/php-jwt/tree/v7.0.5" + }, + "time": "2026-04-01T20:38:03+00:00" + }, { "name": "fruitcake/php-cors", "version": "v1.4.0", @@ -2220,6 +2284,74 @@ }, "time": "2026-02-13T12:50:40+00:00" }, + { + "name": "kovah/laravel-socialite-oidc", + "version": "v0.7.0", + "source": { + "type": "git", + "url": "https://github.com/Kovah/laravel-socialite-oidc.git", + "reference": "7c4495d833f041e74726da99d6588803eedf6b9e" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/Kovah/laravel-socialite-oidc/zipball/7c4495d833f041e74726da99d6588803eedf6b9e", + "reference": "7c4495d833f041e74726da99d6588803eedf6b9e", + "shasum": "" + }, + "require": { + "ext-json": "*", + "firebase/php-jwt": "^6.4|^7.0", + "illuminate/http": "^9.0 | ^10.0 | ^11.0 | ^12.0 | ^13.0", + "illuminate/support": "^9.0 | ^10.0 | ^11.0 | ^12.0 | ^13.0", + "php": "^8.1", + "socialiteproviders/manager": "^4.0" + }, + "conflict": { + "jp-gauthier/socialiteproviders-oidc": "*" + }, + "type": "library", + "autoload": { + "psr-4": { + "SocialiteProviders\\OIDC\\": "src" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "JPG Dev", + "homepage": "https://jpgdev.com" + }, + { + "name": "Kevin Woblick", + "email": "contact@woblick.dev", + "homepage": "https://woblick.dev", + "role": "Developer" + } + ], + "description": "OpenID Connect OAuth2 Provider for Laravel Socialite", + "homepage": "https://github.com/kovah/laravel-socialite-oidc", + "keywords": [ + "laravel", + "oauth", + "oidc", + "provider", + "socialite" + ], + "support": { + "issues": "https://github.com/Kovah/laravel-socialite-oidc/issues", + "source": "https://github.com/Kovah/laravel-socialite-oidc/tree/v0.7.0" + }, + "funding": [ + { + "url": "https://github.com/sponsors/kovah", + "type": "github" + } + ], + "time": "2026-03-18T10:06:36+00:00" + }, { "name": "laravel/framework", "version": "v11.51.0", @@ -2555,6 +2687,78 @@ }, "time": "2026-04-14T13:33:34+00:00" }, + { + "name": "laravel/socialite", + "version": "v5.26.1", + "source": { + "type": "git", + "url": "https://github.com/laravel/socialite.git", + "reference": "db6ec2ee967b7f06412c3a0cf1daaf072f4752a4" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/laravel/socialite/zipball/db6ec2ee967b7f06412c3a0cf1daaf072f4752a4", + "reference": "db6ec2ee967b7f06412c3a0cf1daaf072f4752a4", + "shasum": "" + }, + "require": { + "ext-json": "*", + "firebase/php-jwt": "^6.4|^7.0", + "guzzlehttp/guzzle": "^6.0|^7.0", + "illuminate/contracts": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0|^13.0", + "illuminate/http": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0|^13.0", + "illuminate/support": "^6.0|^7.0|^8.0|^9.0|^10.0|^11.0|^12.0|^13.0", + "league/oauth1-client": "^1.11", + "php": "^7.2|^8.0", + "phpseclib/phpseclib": "^3.0" + }, + "require-dev": { + "mockery/mockery": "^1.0", + "orchestra/testbench": "^4.18|^5.20|^6.47|^7.55|^8.36|^9.15|^10.8|^11.0", + "phpstan/phpstan": "^1.12.23", + "phpunit/phpunit": "^8.0|^9.3|^10.4|^11.5|^12.0" + }, + "type": "library", + "extra": { + "laravel": { + "aliases": { + "Socialite": "Laravel\\Socialite\\Facades\\Socialite" + }, + "providers": [ + "Laravel\\Socialite\\SocialiteServiceProvider" + ] + }, + "branch-alias": { + "dev-master": "5.x-dev" + } + }, + "autoload": { + "psr-4": { + "Laravel\\Socialite\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Taylor Otwell", + "email": "taylor@laravel.com" + } + ], + "description": "Laravel wrapper around OAuth 1 & OAuth 2 libraries.", + "homepage": "https://laravel.com", + "keywords": [ + "laravel", + "oauth" + ], + "support": { + "issues": "https://github.com/laravel/socialite/issues", + "source": "https://github.com/laravel/socialite" + }, + "time": "2026-03-29T14:50:53+00:00" + }, { "name": "laravel/tinker", "version": "v2.11.1", @@ -3152,6 +3356,82 @@ ], "time": "2024-09-21T08:32:55+00:00" }, + { + "name": "league/oauth1-client", + "version": "v1.11.0", + "source": { + "type": "git", + "url": "https://github.com/thephpleague/oauth1-client.git", + "reference": "f9c94b088837eb1aae1ad7c4f23eb65cc6993055" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/thephpleague/oauth1-client/zipball/f9c94b088837eb1aae1ad7c4f23eb65cc6993055", + "reference": "f9c94b088837eb1aae1ad7c4f23eb65cc6993055", + "shasum": "" + }, + "require": { + "ext-json": "*", + "ext-openssl": "*", + "guzzlehttp/guzzle": "^6.0|^7.0", + "guzzlehttp/psr7": "^1.7|^2.0", + "php": ">=7.1||>=8.0" + }, + "require-dev": { + "ext-simplexml": "*", + "friendsofphp/php-cs-fixer": "^2.17", + "mockery/mockery": "^1.3.3", + "phpstan/phpstan": "^0.12.42", + "phpunit/phpunit": "^7.5||9.5" + }, + "suggest": { + "ext-simplexml": "For decoding XML-based responses." + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.0-dev", + "dev-develop": "2.0-dev" + } + }, + "autoload": { + "psr-4": { + "League\\OAuth1\\Client\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ben Corlett", + "email": "bencorlett@me.com", + "homepage": "http://www.webcomm.com.au", + "role": "Developer" + } + ], + "description": "OAuth 1.0 Client Library", + "keywords": [ + "Authentication", + "SSO", + "authorization", + "bitbucket", + "identity", + "idp", + "oauth", + "oauth1", + "single sign on", + "trello", + "tumblr", + "twitter" + ], + "support": { + "issues": "https://github.com/thephpleague/oauth1-client/issues", + "source": "https://github.com/thephpleague/oauth1-client/tree/v1.11.0" + }, + "time": "2024-12-10T19:59:05+00:00" + }, { "name": "league/uri", "version": "7.8.1", @@ -4600,6 +4880,116 @@ ], "time": "2025-12-27T19:41:33+00:00" }, + { + "name": "phpseclib/phpseclib", + "version": "3.0.51", + "source": { + "type": "git", + "url": "https://github.com/phpseclib/phpseclib.git", + "reference": "d59c94077f9c9915abb51ddb52ce85188ece1748" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/phpseclib/phpseclib/zipball/d59c94077f9c9915abb51ddb52ce85188ece1748", + "reference": "d59c94077f9c9915abb51ddb52ce85188ece1748", + "shasum": "" + }, + "require": { + "paragonie/constant_time_encoding": "^1|^2|^3", + "paragonie/random_compat": "^1.4|^2.0|^9.99.99", + "php": ">=5.6.1" + }, + "require-dev": { + "phpunit/phpunit": "*" + }, + "suggest": { + "ext-dom": "Install the DOM extension to load XML formatted public keys.", + "ext-gmp": "Install the GMP (GNU Multiple Precision) extension in order to speed up arbitrary precision integer arithmetic operations.", + "ext-libsodium": "SSH2/SFTP can make use of some algorithms provided by the libsodium-php extension.", + "ext-mcrypt": "Install the Mcrypt extension in order to speed up a few other cryptographic operations.", + "ext-openssl": "Install the OpenSSL extension in order to speed up a wide variety of cryptographic operations." + }, + "type": "library", + "autoload": { + "files": [ + "phpseclib/bootstrap.php" + ], + "psr-4": { + "phpseclib3\\": "phpseclib/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Jim Wigginton", + "email": "terrafrost@php.net", + "role": "Lead Developer" + }, + { + "name": "Patrick Monnerat", + "email": "pm@datasphere.ch", + "role": "Developer" + }, + { + "name": "Andreas Fischer", + "email": "bantu@phpbb.com", + "role": "Developer" + }, + { + "name": "Hans-Jürgen Petrich", + "email": "petrich@tronic-media.com", + "role": "Developer" + }, + { + "name": "Graham Campbell", + "email": "graham@alt-three.com", + "role": "Developer" + } + ], + "description": "PHP Secure Communications Library - Pure-PHP implementations of RSA, AES, SSH2, SFTP, X.509 etc.", + "homepage": "http://phpseclib.sourceforge.net", + "keywords": [ + "BigInteger", + "aes", + "asn.1", + "asn1", + "blowfish", + "crypto", + "cryptography", + "encryption", + "rsa", + "security", + "sftp", + "signature", + "signing", + "ssh", + "twofish", + "x.509", + "x509" + ], + "support": { + "issues": "https://github.com/phpseclib/phpseclib/issues", + "source": "https://github.com/phpseclib/phpseclib/tree/3.0.51" + }, + "funding": [ + { + "url": "https://github.com/terrafrost", + "type": "github" + }, + { + "url": "https://www.patreon.com/phpseclib", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/phpseclib/phpseclib", + "type": "tidelift" + } + ], + "time": "2026-04-10T01:33:53+00:00" + }, { "name": "pragmarx/google2fa", "version": "v9.0.0", @@ -5636,6 +6026,80 @@ ], "time": "2026-03-13T08:38:20+00:00" }, + { + "name": "socialiteproviders/manager", + "version": "4.9.2", + "source": { + "type": "git", + "url": "https://github.com/SocialiteProviders/Manager.git", + "reference": "35372dc62787e61e91cfec73f45fd5d5ae0f8891" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/SocialiteProviders/Manager/zipball/35372dc62787e61e91cfec73f45fd5d5ae0f8891", + "reference": "35372dc62787e61e91cfec73f45fd5d5ae0f8891", + "shasum": "" + }, + "require": { + "illuminate/support": "^11.0 || ^12.0 || ^13.0", + "laravel/socialite": "^5.5", + "php": "^8.2" + }, + "require-dev": { + "mockery/mockery": "^1.2", + "phpunit/phpunit": "^9.0" + }, + "type": "library", + "extra": { + "laravel": { + "providers": [ + "SocialiteProviders\\Manager\\ServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "SocialiteProviders\\Manager\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Andy Wendt", + "email": "andy@awendt.com" + }, + { + "name": "Anton Komarev", + "email": "a.komarev@cybercog.su" + }, + { + "name": "Miguel Piedrafita", + "email": "soy@miguelpiedrafita.com" + }, + { + "name": "atymic", + "email": "atymicq@gmail.com", + "homepage": "https://atymic.dev" + } + ], + "description": "Easily add new or override built-in providers in Laravel Socialite.", + "homepage": "https://socialiteproviders.com", + "keywords": [ + "laravel", + "manager", + "oauth", + "providers", + "socialite" + ], + "support": { + "issues": "https://github.com/socialiteproviders/manager/issues", + "source": "https://github.com/socialiteproviders/manager" + }, + "time": "2026-03-18T22:13:24+00:00" + }, { "name": "spatie/invade", "version": "2.1.0", diff --git a/config/services.php b/config/services.php index 4460f0e..0b3b30c 100644 --- a/config/services.php +++ b/config/services.php @@ -35,4 +35,11 @@ return [ 'secret' => env('STRIPE_SECRET'), ], + 'oidc' => [ + 'base_url' => env('OIDC_BASE_URL'), + 'client_id' => env('OIDC_CLIENT_ID'), + 'client_secret' => env('OIDC_CLIENT_SECRET'), + 'redirect' => env('OIDC_REDIRECT_URI'), + ], + ]; diff --git a/database/migrations/2026_04_26_162522_add_socialite_fields_to_users_table.php b/database/migrations/2026_04_26_162522_add_socialite_fields_to_users_table.php new file mode 100644 index 0000000..96d3e8d --- /dev/null +++ b/database/migrations/2026_04_26_162522_add_socialite_fields_to_users_table.php @@ -0,0 +1,31 @@ +string('provider_name')->nullable(); + $table->string('provider_id')->nullable(); + $table->unique(['provider_name', 'provider_id']); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('users', function (Blueprint $table) { + $table->dropUnique(['provider_name', 'provider_id']); + $table->dropColumn(['provider_name', 'provider_id']); + }); + } +}; diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index e0e0b58..a611d1f 100644 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -54,6 +54,10 @@ Login + + Login with OIDC + + Forgot Your Password? diff --git a/routes/web.php b/routes/web.php index 3ff133d..ee3faf9 100644 --- a/routes/web.php +++ b/routes/web.php @@ -14,6 +14,10 @@ if (env('APP_ENV') === 'production') { URL::forceScheme('https'); } Auth::routes(['register' => false]); + +Route::get('auth/social/{provider}', 'Auth\SocialiteController@redirectToProvider'); +Route::get('auth/social/{provider}/callback', 'Auth\SocialiteController@handleProviderCallback'); + Route::get('/', [ 'uses' => 'PagesController@home']); Route::get('home', [ 'uses' => 'PagesController@home']); Route::get('winningbidderlist', [ 'uses' => 'PagesController@winningbidderlist']); From ad02f65b54f535d5f9f7214f2767d57d85c6d84a Mon Sep 17 00:00:00 2001 From: Russ Long Date: Sun, 26 Apr 2026 16:38:43 -0400 Subject: [PATCH 2/2] Add UserResource and OIDC linking to Filament user menu --- app/Filament/Resources/UserResource.php | 76 +++++++++++++++++++ .../UserResource/Pages/CreateUsers.php | 11 +++ .../UserResource/Pages/EditUsers.php | 11 +++ .../UserResource/Pages/ListUsers.php | 11 +++ .../Controllers/Auth/SocialiteController.php | 10 +++ app/Providers/Filament/AdminPanelProvider.php | 8 ++ 6 files changed, 127 insertions(+) create mode 100644 app/Filament/Resources/UserResource.php create mode 100644 app/Filament/Resources/UserResource/Pages/CreateUsers.php create mode 100644 app/Filament/Resources/UserResource/Pages/EditUsers.php create mode 100644 app/Filament/Resources/UserResource/Pages/ListUsers.php diff --git a/app/Filament/Resources/UserResource.php b/app/Filament/Resources/UserResource.php new file mode 100644 index 0000000..69a2489 --- /dev/null +++ b/app/Filament/Resources/UserResource.php @@ -0,0 +1,76 @@ +components([ + TextInput::make('name') + ->required() + ->maxLength(255), + TextInput::make('email') + ->email() + ->required() + ->maxLength(255), + TextInput::make('provider_name') + ->label('OIDC Provider') + ->disabled(), + TextInput::make('provider_id') + ->label('OIDC ID') + ->disabled(), + ]); + } + + public static function table(Table $table): Table + { + return $table + ->columns([ + TextColumn::make('name')->sortable()->searchable(), + TextColumn::make('email')->sortable()->searchable(), + TextColumn::make('provider_name')->label('OIDC Provider'), + TextColumn::make('provider_id')->label('OIDC ID'), + TextColumn::make('created_at')->dateTime()->sortable(), + ]) + ->filters([ + // + ]) + ->recordActions([ + EditAction::make(), + ]) + ->toolbarActions([ + BulkActionGroup::make([ + DeleteBulkAction::make(), + ]), + ]); + } + + public static function getPages(): array + { + return [ + 'index' => UserResource\Pages\ListUsers::route('/'), + 'create' => UserResource\Pages\CreateUsers::route('/create'), + 'edit' => UserResource\Pages\EditUsers::route('/{record}/edit'), + ]; + } +} diff --git a/app/Filament/Resources/UserResource/Pages/CreateUsers.php b/app/Filament/Resources/UserResource/Pages/CreateUsers.php new file mode 100644 index 0000000..6d217e3 --- /dev/null +++ b/app/Filament/Resources/UserResource/Pages/CreateUsers.php @@ -0,0 +1,11 @@ +with('error', 'Authentication failed.'); } + if (Auth::check()) { + $user = Auth::user(); + $user->update([ + 'provider_name' => $provider, + 'provider_id' => $socialUser->getId(), + ]); + + return redirect()->intended('/admin')->with('status', 'Account linked successfully!'); + } + // Find user by provider_id $user = User::where('provider_name', $provider) ->where('provider_id', $socialUser->getId()) diff --git a/app/Providers/Filament/AdminPanelProvider.php b/app/Providers/Filament/AdminPanelProvider.php index 1038366..a97ee8d 100644 --- a/app/Providers/Filament/AdminPanelProvider.php +++ b/app/Providers/Filament/AdminPanelProvider.php @@ -21,6 +21,8 @@ use Illuminate\View\Middleware\ShareErrorsFromSession; use Filament\Support\Facades\FilamentView; use Illuminate\Support\Facades\Blade; +use Filament\Navigation\MenuItem; + class AdminPanelProvider extends PanelProvider { public function boot() @@ -51,6 +53,12 @@ class AdminPanelProvider extends PanelProvider ->login() ->brandName(env('APP_NAME')) ->homeUrl('/') + ->userMenuItems([ + MenuItem::make() + ->label('Link OIDC Account') + ->icon('heroicon-o-link') + ->url(fn (): string => url('auth/social/oidc')), + ]) ->colors([ 'primary' => Color::Amber, ])