authorizationRequest(); } catch (MicrosoftAuthenticationException $exception) { return $this->failure($request, $exception->getMessage()); } $request->session()->put('microsoft_oidc', [ ...$authorization['flow'], 'intent' => 'login', 'user_id' => null, ]); return redirect()->away($authorization['url']); } public function callback( Request $request, MicrosoftOidcClient $client, MicrosoftIdentityService $identities, ): RedirectResponse { $flow = $request->session()->pull('microsoft_oidc'); if (! is_array($flow) || ! is_string($flow['state'] ?? null) || ! is_string($flow['nonce'] ?? null) || ! is_string($flow['code_verifier'] ?? null) || ! in_array($flow['intent'] ?? null, ['login', 'link'], true) || ! is_string($request->query('state')) || ! hash_equals($flow['state'], $request->query('state')) || ! is_int($flow['created_at'] ?? null) || $flow['created_at'] < time() - 600) { return $this->failure($request, 'O pedido de autenticação expirou ou não é válido.'); } if ($request->filled('error')) { return $this->failure($request, 'A autenticação Microsoft foi cancelada ou recusada.'); } $code = $request->query('code'); if (! is_string($code) || $code === '') { return $this->failure($request, 'O Microsoft Entra não devolveu o código de autenticação.'); } try { $claims = $client->authenticate($code, (string) $flow['code_verifier'], (string) $flow['nonce']); if ($flow['intent'] === 'link') { $user = $request->user(); if ($user === null || $user->id !== ($flow['user_id'] ?? null)) { throw new MicrosoftAuthenticationException('A sessão local mudou durante a associação da identidade.'); } $identities->link($user, $claims, $request); return redirect()->route('security.edit')->with('success', 'Identidade Microsoft associada com sucesso.'); } $user = $identities->userForLogin($claims, $request); Auth::login($user); $request->session()->regenerate(); return redirect()->intended(route('dashboard', absolute: false)); } catch (MicrosoftAuthenticationException $exception) { return $this->failure($request, $exception->getMessage()); } catch (Throwable $exception) { Log::warning('Falha inesperada na autenticação Microsoft.', [ 'exception' => $exception::class, ]); return $this->failure($request, 'Não foi possível concluir a autenticação Microsoft.'); } } private function failure(Request $request, string $message): RedirectResponse { return redirect()->route($request->user() === null ? 'login' : 'security.edit')->with('error', $message); } }