From 020e473dc971c658c07e84ea1f1bcf7b4f21e70f Mon Sep 17 00:00:00 2001 From: Chris Mancuso Date: Thu, 5 Mar 2026 18:43:19 -0600 Subject: [PATCH] controller update --- .../Controllers/Auth/EveLoginController.php | 71 +++++++++++++++++++ .../Controllers/AuthEveLoginController.php | 10 +++ app/Models/Auth/User.php | 31 ++++---- app/Providers/AppServiceProvider.php | 6 +- app/Providers/EventServiceProvider.php | 15 ++++ .../0001_01_01_000000_create_users_table.php | 30 ++++---- resources/views/auth/eve.blade.php | 32 +++++++++ resources/views/dashboard/dashboard.blade.php | 22 ++++++ routes/web.php | 21 ++++-- 9 files changed, 196 insertions(+), 42 deletions(-) create mode 100644 app/Http/Controllers/Auth/EveLoginController.php create mode 100644 app/Http/Controllers/AuthEveLoginController.php create mode 100644 app/Providers/EventServiceProvider.php create mode 100644 resources/views/auth/eve.blade.php create mode 100644 resources/views/dashboard/dashboard.blade.php diff --git a/app/Http/Controllers/Auth/EveLoginController.php b/app/Http/Controllers/Auth/EveLoginController.php new file mode 100644 index 0000000..eb5eded --- /dev/null +++ b/app/Http/Controllers/Auth/EveLoginController.php @@ -0,0 +1,71 @@ +redirect(); + } + + public function handleProviderCallback(Request $request): RedirectResponse + { + try { + // Stateless can help in some deployments, but keep stateful by default. + // If you run into "Invalid state" issues behind proxies, switch to ->stateless() + $ssoUser = Socialite::driver('eveonline')->user(); + + // Socialite user basics + $characterId = (int) $ssoUser->getId(); + $characterName = $ssoUser->getName() ?: ($ssoUser->getNickname() ?? 'Unknown'); + + // Provider-specific extra payload sometimes appears in user array / token response. + // We’ll defensively extract what we can. + $raw = $ssoUser->user ?? []; + $characterOwnerHash = + $raw['CharacterOwnerHash'] ?? $raw['character_owner_hash'] ?? $raw['owner_hash'] ?? ''; + + $token = $ssoUser->token; + $refreshToken = $ssoUser->refreshToken ?? null; + $expiresIn = $ssoUser->expiresIn ?? null; + + $user = User::updateOrCreate( + ['character_id' => $characterId], + [ + 'character_name' => $characterName, + 'character_owner_hash' => $characterOwnerHash, + 'token' => $token, + 'refresh_token' => $refreshToken, + 'expiresIn' => $expiresIn, + // "user" holds jwt - you can set it later when you add JWT issuance. + 'user' => null, + ] + ); + + Auth::login($user, true); + + $request->session()->regenerate(); + + return redirect()->route('dashboard'); + } catch (Throwable $e) { + // For now: fail back to login with a generic error. + // Later you can add logging/telemetry. + return redirect()->route('login')->with('error', 'SSO login failed. Please try again.'); + } + } +} \ No newline at end of file diff --git a/app/Http/Controllers/AuthEveLoginController.php b/app/Http/Controllers/AuthEveLoginController.php new file mode 100644 index 0000000..4815daa --- /dev/null +++ b/app/Http/Controllers/AuthEveLoginController.php @@ -0,0 +1,10 @@ + */ - use HasFactory, Notifiable; + use Notifiable; - /** - * The attributes that are mass assignable. - * - * @var list - */ protected $fillable = [ - 'character_id', - 'character_name', 'character_owner_hash', + 'character_name', + 'character_id', + 'token', + 'refresh_token', + 'expiresIn', + 'user', // holds jwt (per spec) ]; - /** - * The attributes that should be hidden for serialization. - * - * @var list - */ protected $hidden = [ + 'token', + 'refresh_token', 'remember_token', ]; + protected function casts(): array + { + return [ + 'expiresIn' => 'integer', + ]; + } } diff --git a/app/Providers/AppServiceProvider.php b/app/Providers/AppServiceProvider.php index 05ac4c7..06d02f1 100644 --- a/app/Providers/AppServiceProvider.php +++ b/app/Providers/AppServiceProvider.php @@ -20,8 +20,8 @@ class AppServiceProvider extends ServiceProvider */ public function boot(): void { - Event::listen(function (\SocialiteProvider\Manager\SocialiteWasCalled $event) { - $event->extendSocialite('eveonline', \SocialiteProviders\Eveonline\Provider::class); - }); + //Event::listen(function (\SocialiteProvider\Manager\SocialiteWasCalled $event) { + // $event->extendSocialite('eveonline', \SocialiteProviders\Eveonline\Provider::class); + //}); } } diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php new file mode 100644 index 0000000..6d645dc --- /dev/null +++ b/app/Providers/EventServiceProvider.php @@ -0,0 +1,15 @@ + [ + // registers Eve Online driver "eveonline" + \SocialiteProviders\EveOnline\EveOnlineExtendSocialite::class.'@handle'; + ]; + ]; +} \ No newline at end of file diff --git a/database/migrations/0001_01_01_000000_create_users_table.php b/database/migrations/0001_01_01_000000_create_users_table.php index b70f002..e5036f8 100644 --- a/database/migrations/0001_01_01_000000_create_users_table.php +++ b/database/migrations/0001_01_01_000000_create_users_table.php @@ -11,32 +11,28 @@ return new class extends Migration */ public function up(): void { + if(!Schema::hasTable('users')) { Schema::create('users', function (Blueprint $table) { $table->id(); - $table->string('character_id'); + + $table->string('character_owner_hash')->index(); $table->string('character_name'); - $table->string('email')->unique(); - $table->timestamp('email_verified_at')->nullable(); - $table->string('password'); - $table->string('character_owner_hash'); - $table->string('token'); - $table->string('refresh_token'); - $table->integer('expiresIn'); - $table->string('user_jwt_token'); + $table->unsignedBigInteger('character_id')->unique(); + + $table->text('token'); + $table->text('refresh_token')->nullable(); + $table->integer('expiresIn')->nullable(); + + // As requested: "user" holds jwt. (Note: naming a column "user" can be confusing later; + // consider "jwt" in future refactors, but this honors your spec.) + $table->text('user')->nullable(); + $table->rememberToken(); $table->timestamps(); }); } - if(!Schema::hasTable('password_reset_tokens')) { - Schema::create('password_reset_tokens', function (Blueprint $table) { - $table->string('email')->primary(); - $table->string('token'); - $table->timestamp('created_at')->nullable(); - }); - } - if(!Schema::hasTable('sessions')) { Schema::create('sessions', function (Blueprint $table) { $table->string('id')->primary(); diff --git a/resources/views/auth/eve.blade.php b/resources/views/auth/eve.blade.php new file mode 100644 index 0000000..5af9e13 --- /dev/null +++ b/resources/views/auth/eve.blade.php @@ -0,0 +1,32 @@ + + + + + + EVE SSO Login + + + +
+ @if (session('error')) +
{{ session('error') }}
+ @endif + +

Sign in with EVE Online

+ + + {{-- Put the official EVE SSO image in: public/images/eve-sso.png --}} + EVE Online Single Sign-On + + +
Click the image to begin the EVE Online SSO flow.
+
+ + \ No newline at end of file diff --git a/resources/views/dashboard/dashboard.blade.php b/resources/views/dashboard/dashboard.blade.php new file mode 100644 index 0000000..d689743 --- /dev/null +++ b/resources/views/dashboard/dashboard.blade.php @@ -0,0 +1,22 @@ + + + + + + Dashboard + + +
+
+

Hello World

+ +
+ @csrf + +
+
+ +

Logged in as: {{ auth()->user()->character_name }} ({{ auth()->user()->character_id }})

+
+ + \ No newline at end of file diff --git a/routes/web.php b/routes/web.php index 43ea176..5920b24 100644 --- a/routes/web.php +++ b/routes/web.php @@ -9,11 +9,20 @@ Route::get('/', function () { return view('welcome'); }); -Auth::routes(); +Route::get('/', [EveLoginController::class, 'showLogin'])->name('login'); -Route::get('/dashboard', [App\Http\Controllers\DashboardController::class, 'index'])->name('dashboard'); +Route::get('/login/eve', [EveLoginController::class, 'redirectToProvider'])->name('login.eve'); +Route::get('/login/eve/callback', [EveLoginController::class, 'handleProviderCallback'])->name('login.eve.callback'); -Route::controller(LoginController::class)->group(function () { - Route::get('auth/eveonline', 'redirectToEve')->name('auth.eveonline'); - Route::get('auth/eveonline/callback', 'handleEveonlineCallback'); -}); +Route::middleware('auth')->group(function () { + Route::get('/dashboard', function () { + return view('dashboard'); + })->name('dashboard'); + + Route::post('/logout', function () { + auth()->logout(); + request()->session()->invalidate(); + request()->session()->regenerateToken(); + return redirect()->route('login'); + })->name('logout'); +}); \ No newline at end of file