query('return_to'); if (is_string($returnTo) && $returnTo !== '') { $request->session()->put('tenant_oauth_return_to', $returnTo); } return Socialite::driver('google') ->scopes(['openid', 'profile', 'email']) ->with(['prompt' => 'select_account']) ->redirect(); } public function callback(Request $request) { try { $googleUser = Socialite::driver('google')->user(); } catch (Throwable $exception) { Log::warning('Tenant admin Google sign-in failed', [ 'message' => $exception->getMessage(), ]); return $this->sendBackWithError($request, 'google_failed', 'Unable to complete Google sign-in.'); } $email = $googleUser->getEmail(); if (! $email) { return $this->sendBackWithError($request, 'google_failed', 'Google account did not provide an email address.'); } /** @var User|null $user */ $user = User::query()->where('email', $email)->first(); if (! $user || ! in_array($user->role, ['tenant_admin', 'super_admin'], true)) { return $this->sendBackWithError($request, 'google_no_match', 'No tenant admin account is linked to this Google address.'); } $user->forceFill([ 'name' => $googleUser->getName() ?: $user->name, 'email_verified_at' => $user->email_verified_at ?? now(), ])->save(); Auth::login($user, true); $request->session()->regenerate(); $returnTo = $request->session()->pull('tenant_oauth_return_to'); if (is_string($returnTo)) { $decoded = $this->decodeReturnTo($returnTo, $request); if ($decoded) { return redirect()->to($decoded); } } return redirect()->intended('/event-admin/dashboard'); } private function sendBackWithError(Request $request, string $code, string $message): RedirectResponse { $query = [ 'error' => $code, 'error_description' => $message, ]; if ($request->session()->has('tenant_oauth_return_to')) { $query['return_to'] = $request->session()->get('tenant_oauth_return_to'); } return redirect()->route('tenant.admin.login', $query); } private function decodeReturnTo(string $encoded, Request $request): ?string { $padded = str_pad($encoded, strlen($encoded) + ((4 - (strlen($encoded) % 4)) % 4), '='); $normalized = strtr($padded, '-_', '+/'); $decoded = base64_decode($normalized); if (! is_string($decoded) || $decoded === '') { return null; } $targetHost = parse_url($decoded, PHP_URL_HOST); $appHost = parse_url($request->getSchemeAndHttpHost(), PHP_URL_HOST); if ($targetHost && $appHost && ! Str::endsWith($targetHost, $appHost)) { return null; } return $decoded; } }