intended(filament()->getUrl()); } try { ['url' => $url, 'state' => $state, 'code_verifier' => $verifier] = PireonClient::forRedirect()->authorizationUrl(); } catch (PireonException $e) { return $this->fail($e, route('login')); } $request->session()->put('pireon.state', $state); $request->session()->put('pireon.code_verifier', $verifier); // Remember where the user was headed before the redirect, so the // callback can send them back there. if ($target = $request->query('intended')) { $request->session()->put('url.intended', $target); } return redirect()->away($url); } /** * Step 2 — the identity server sends the browser back with a code. */ public function callback(Request $request): RedirectResponse { // The user pressed "deny", or the server refused the request. if ($request->filled('error')) { return redirect()->route('login')->with('error', __('pireon.denied', [ 'reason' => (string) $request->query('error_description', $request->query('error')), ])); } $state = $request->session()->pull('pireon.state'); $verifier = $request->session()->pull('pireon.code_verifier'); // CSRF protection for the callback: a code arriving with a state we // did not issue is not the result of a login we started. if (blank($state) || ! hash_equals((string) $state, (string) $request->query('state'))) { return $this->fail(PireonException::invalidState(), route('login')); } if (blank($verifier) || blank($request->query('code'))) { return $this->fail(PireonException::invalidState(), route('login')); } try { $token = PireonClient::forRedirect()->exchangeCode((string) $request->query('code'), (string) $verifier); $identity = $this->client->identity($token->accessToken); } catch (PireonException $e) { return $this->fail($e, route('login')); } if (! $identity->isUsable()) { return redirect()->route('login')->with('error', $identity->isApproved() ? __('pireon.inactive') : __('pireon.pending_approval')); } $user = $this->sync->handle($identity); // Rotate the session id so a fixated pre-login session cannot be // reused now that it carries an authenticated identity. $request->session()->regenerate(); Auth::login($user, remember: true); $this->tokens->put($token, viaRedirect: true); if ($user->locale) { $request->session()->put(config('locales.session_key'), $user->locale); } return redirect()->intended(filament()->getUrl()); } public function logout(Request $request): RedirectResponse { $this->tokens->forget(); Auth::logout(); $request->session()->invalidate(); $request->session()->regenerateToken(); return redirect()->route('login'); } protected function fail(PireonException $e, string $to): RedirectResponse { Log::warning('Pireon login failed', [ 'message' => $e->getMessage(), 'status' => $e->status, ]); return redirect()->to($to)->with('error', $e->getMessage()); } }