substr((string) Arr::get($azureConfig, 'client_id', ''), 0, 4), 'redirect_uri' => Arr::get($azureConfig, 'redirect'), 'tenant' => Arr::get($azureConfig, 'tenant'), ]); $response = Socialite::driver('azure')->redirect(); Log::info('[Azure SSO] Redirect URL generated', [ 'redirect_url' => $response->getTargetUrl(), ]); return $response; } /** * Handle the callback from Azure AD after authentication. * Logs request parameters, the resolved Azure user, and the upserted local user. * Wraps the entire flow in a try/catch to capture and log any exceptions. */ public function callback(): RedirectResponse { try { return $this->processCallback(); } catch (\Throwable $e) { Log::error('[Azure SSO] Exception during callback', [ 'message' => $e->getMessage(), 'exception' => $e->getTraceAsString(), ]); throw $e; } } /** * Log the user out and redirect to landing page. */ public function logout(Request $request): RedirectResponse { ActivityLogger::log('logout', auth()->id()); auth()->logout(); $request->session()->invalidate(); $request->session()->regenerateToken(); return redirect('/'); } /** * Execute the full Azure AD callback flow: resolve the user, upsert the local record, * assign a default role if needed, log the user in, and record the activity. */ private function processCallback(): RedirectResponse { Log::info('[Azure SSO] Callback received', [ 'query_code' => substr((string) request()->query('code', ''), 0, 8).'…', 'query_state' => request()->query('state'), 'query_error' => request()->query('error'), 'query_error_description' => request()->query('error_description'), ]); $azureUser = Socialite::driver('azure')->user(); Log::info('[Azure SSO] Azure user resolved', [ 'azure_id' => $azureUser->getId(), 'email' => $azureUser->getEmail(), 'mail' => Arr::get($azureUser->user, 'mail'), 'name' => $azureUser->getName(), 'job_title' => Arr::get($azureUser->user, 'jobTitle'), 'department' => Arr::get($azureUser->user, 'department'), 'company' => Arr::get($azureUser->user, 'companyName'), ]); Log::info('[Azure SSO] Full Azure user dump', json_decode(json_encode($azureUser), true)); try { $user = User::query()->updateOrCreate( ['username' => $azureUser->getEmail()], [ 'name' => $azureUser->getName(), 'email' => $azureUser->user['mail'] ?? $azureUser->getEmail(), 'azure_id' => $azureUser->getId(), 'photo' => $azureUser->getAvatar(), 'job_title' => Arr::get($azureUser->user, 'jobTitle'), 'department' => Arr::get($azureUser->user, 'department'), 'company_name' => Arr::get($azureUser->user, 'companyName'), 'phone' => Arr::get($azureUser->user, 'mobilePhone', Arr::get($azureUser->user, 'businessPhones.0')), 'email_verified_at' => now(), ] ); Log::info('[Azure SSO] Local user upserted', [ 'user_id' => $user->id, 'email' => $user->email, 'was_recent' => $user->wasRecentlyCreated, 'role_id' => $user->role_id, ]); if ($user->role_id === null) { $user->update(['role_id' => Role::where('name', 'user')->first()->id]); Log::info('[Azure SSO] Default role assigned', [ 'user_id' => $user->id, 'role_id' => $user->role_id, ]); } auth()->login($user); ActivityLogger::log('login', $user->id, metadata: ['email' => $user->email, 'firm_name' => Arr::get($azureUser->user, 'companyName')]); } catch (QueryException $e) { Log::error('[Azure SSO] Database error during user upsert', ['message' => $e->getMessage(), 'email' => $azureUser->getEmail()]); return redirect('/')->with('error', 'Something went wrong during sign-in. Please try again or contact support.'); } return redirect('/'); } }