X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/e743cd3f606fb8a2e432813f7c84fed1093f68c4..refs/pull/2511/head:/app/Auth/Access/Guards/LdapSessionGuard.php diff --git a/app/Auth/Access/Guards/LdapSessionGuard.php b/app/Auth/Access/Guards/LdapSessionGuard.php index 6c416bf30..652141c0c 100644 --- a/app/Auth/Access/Guards/LdapSessionGuard.php +++ b/app/Auth/Access/Guards/LdapSessionGuard.php @@ -3,13 +3,17 @@ namespace BookStack\Auth\Access\Guards; use BookStack\Auth\Access\LdapService; +use BookStack\Auth\Access\RegistrationService; use BookStack\Auth\User; use BookStack\Auth\UserRepo; use BookStack\Exceptions\LdapException; use BookStack\Exceptions\LoginAttemptException; use BookStack\Exceptions\LoginAttemptEmailNeededException; +use BookStack\Exceptions\UserRegistrationException; use Illuminate\Contracts\Auth\UserProvider; use Illuminate\Contracts\Session\Session; +use Illuminate\Support\Facades\Hash; +use Illuminate\Support\Str; class LdapSessionGuard extends ExternalBaseSessionGuard { @@ -23,11 +27,11 @@ class LdapSessionGuard extends ExternalBaseSessionGuard UserProvider $provider, Session $session, LdapService $ldapService, - UserRepo $userRepo + RegistrationService $registrationService ) { $this->ldapService = $ldapService; - parent::__construct($name, $provider, $session, $userRepo); + parent::__construct($name, $provider, $session, $registrationService); } /** @@ -40,11 +44,14 @@ class LdapSessionGuard extends ExternalBaseSessionGuard public function validate(array $credentials = []) { $userDetails = $this->ldapService->getUserDetails($credentials['username']); - $this->lastAttempted = $this->provider->retrieveByCredentials([ - 'external_auth_id' => $userDetails['uid'] - ]); - return $this->ldapService->validateUserCredentials($userDetails, $credentials['username'], $credentials['password']); + if (isset($userDetails['uid'])) { + $this->lastAttempted = $this->provider->retrieveByCredentials([ + 'external_auth_id' => $userDetails['uid'] + ]); + } + + return $this->ldapService->validateUserCredentials($userDetails, $credentials['password']); } /** @@ -53,7 +60,6 @@ class LdapSessionGuard extends ExternalBaseSessionGuard * @param array $credentials * @param bool $remember * @return bool - * @throws LoginAttemptEmailNeededException * @throws LoginAttemptException * @throws LdapException */ @@ -61,21 +67,26 @@ class LdapSessionGuard extends ExternalBaseSessionGuard { $username = $credentials['username']; $userDetails = $this->ldapService->getUserDetails($username); - $this->lastAttempted = $user = $this->provider->retrieveByCredentials([ - 'external_auth_id' => $userDetails['uid'] - ]); - if (!$this->ldapService->validateUserCredentials($userDetails, $username, $credentials['password'])) { + $user = null; + if (isset($userDetails['uid'])) { + $this->lastAttempted = $user = $this->provider->retrieveByCredentials([ + 'external_auth_id' => $userDetails['uid'] + ]); + } + + if (!$this->ldapService->validateUserCredentials($userDetails, $credentials['password'])) { return false; } if (is_null($user)) { - $user = $this->freshUserInstanceFromLdapUserDetails($userDetails); + try { + $user = $this->createNewFromLdapAndCreds($userDetails, $credentials); + } catch (UserRegistrationException $exception) { + throw new LoginAttemptException($exception->message); + } } - $this->checkForUserEmail($user, $credentials['email'] ?? ''); - $this->saveIfNew($user); - // Sync LDAP groups if required if ($this->ldapService->shouldSyncGroups()) { $this->ldapService->syncGroups($user, $username); @@ -86,58 +97,27 @@ class LdapSessionGuard extends ExternalBaseSessionGuard } /** - * Save the give user if they don't yet existing in the system. + * Create a new user from the given ldap credentials and login credentials + * @throws LoginAttemptEmailNeededException * @throws LoginAttemptException + * @throws UserRegistrationException */ - protected function saveIfNew(User $user) + protected function createNewFromLdapAndCreds(array $ldapUserDetails, array $credentials): User { - if ($user->exists) { - return; - } - - // Check for existing users with same email - $alreadyUser = $user->newQuery()->where('email', '=', $user->email)->count() > 0; - if ($alreadyUser) { - throw new LoginAttemptException(trans('errors.error_user_exists_different_creds', ['email' => $user->email])); - } - - $user->save(); - $this->userRepo->attachDefaultRole($user); - $this->userRepo->downloadAndAssignUserAvatar($user); - } + $email = trim($ldapUserDetails['email'] ?: ($credentials['email'] ?? '')); - /** - * Ensure the given user has an email. - * Takes the provided email in the request if a value is provided - * and the user does not have an existing email. - * @throws LoginAttemptEmailNeededException - */ - protected function checkForUserEmail(User $user, string $providedEmail) - { - // Request email if missing from user and missing from request - if (is_null($user->email) && !$providedEmail) { + if (empty($email)) { throw new LoginAttemptEmailNeededException(); } - // Add email to model if non-existing and email provided in request - if (!$user->exists && is_null($user->email) && $providedEmail) { - $user->email = $providedEmail; - } - } - - /** - * Create a fresh user instance from details provided by a LDAP lookup. - */ - protected function freshUserInstanceFromLdapUserDetails(array $ldapUserDetails): User - { - $user = new User(); - - $user->name = $ldapUserDetails['name']; - $user->external_auth_id = $ldapUserDetails['uid']; - $user->email = $ldapUserDetails['email']; - $user->email_confirmed = false; + $details = [ + 'name' => $ldapUserDetails['name'], + 'email' => $ldapUserDetails['email'] ?: $credentials['email'], + 'external_auth_id' => $ldapUserDetails['uid'], + 'password' => Str::random(32), + ]; - return $user; + return $this->registrationService->registerUser($details, null, false); } }