+ /**
+ * Process the SAML response for a user. Login the user when
+ * they exist, optionally registering them automatically.
+ *
+ * @throws SamlException
+ * @throws JsonDebugException
+ * @throws UserRegistrationException
+ * @throws StoppedAuthenticationException
+ */
+ public function processLoginCallback(string $samlID, array $samlAttributes): User
+ {
+ $userDetails = $this->getUserDetails($samlID, $samlAttributes);
+ $isLoggedIn = auth()->check();
+
+ if ($this->config['dump_user_details']) {
+ throw new JsonDebugException([
+ 'id_from_idp' => $samlID,
+ 'attrs_from_idp' => $samlAttributes,
+ 'attrs_after_parsing' => $userDetails,
+ ]);
+ }
+
+ if ($userDetails['email'] === null) {
+ throw new SamlException(trans('errors.saml_no_email_address'));
+ }
+
+ if ($isLoggedIn) {
+ throw new SamlException(trans('errors.saml_already_logged_in'), '/login');
+ }
+
+ $user = $this->registrationService->findOrRegister(
+ $userDetails['name'],
+ $userDetails['email'],
+ $userDetails['external_id']
+ );
+
+ if ($user === null) {
+ throw new SamlException(trans('errors.saml_user_not_registered', ['name' => $userDetails['external_id']]), '/login');
+ }
+
+ if ($this->shouldSyncGroups()) {
+ $groups = $this->getUserGroups($samlAttributes);
+ $this->groupSyncService->syncUserWithFoundGroups($user, $groups, $this->config['remove_from_groups']);
+ }
+
+ $this->loginService->login($user, 'saml2');
+
+ return $user;
+ }