3 namespace BookStack\Auth\Access\Guards;
5 use BookStack\Auth\Access\LdapService;
6 use BookStack\Auth\Access\RegistrationService;
7 use BookStack\Auth\User;
8 use BookStack\Exceptions\LdapException;
9 use BookStack\Exceptions\LoginAttemptEmailNeededException;
10 use BookStack\Exceptions\LoginAttemptException;
11 use BookStack\Exceptions\UserRegistrationException;
12 use Illuminate\Contracts\Auth\UserProvider;
13 use Illuminate\Contracts\Session\Session;
14 use Illuminate\Support\Str;
16 class LdapSessionGuard extends ExternalBaseSessionGuard
18 protected $ldapService;
21 * LdapSessionGuard constructor.
23 public function __construct(
25 UserProvider $provider,
27 LdapService $ldapService,
28 RegistrationService $registrationService
30 $this->ldapService = $ldapService;
31 parent::__construct($name, $provider, $session, $registrationService);
35 * Validate a user's credentials.
37 * @param array $credentials
39 * @throws LdapException
43 public function validate(array $credentials = [])
45 $userDetails = $this->ldapService->getUserDetails($credentials['username']);
47 if (isset($userDetails['uid'])) {
48 $this->lastAttempted = $this->provider->retrieveByCredentials([
49 'external_auth_id' => $userDetails['uid'],
53 return $this->ldapService->validateUserCredentials($userDetails, $credentials['password']);
57 * Attempt to authenticate a user using the given credentials.
59 * @param array $credentials
60 * @param bool $remember
62 * @throws LoginAttemptException
63 * @throws LdapException
67 public function attempt(array $credentials = [], $remember = false)
69 $username = $credentials['username'];
70 $userDetails = $this->ldapService->getUserDetails($username);
73 if (isset($userDetails['uid'])) {
74 $this->lastAttempted = $user = $this->provider->retrieveByCredentials([
75 'external_auth_id' => $userDetails['uid'],
79 if (!$this->ldapService->validateUserCredentials($userDetails, $credentials['password'])) {
85 $user = $this->createNewFromLdapAndCreds($userDetails, $credentials);
86 } catch (UserRegistrationException $exception) {
87 throw new LoginAttemptException($exception->message);
91 // Sync LDAP groups if required
92 if ($this->ldapService->shouldSyncGroups()) {
93 $this->ldapService->syncGroups($user, $username);
96 // Attach avatar if non-existent
97 if (!$user->avatar()->exists()) {
98 $this->ldapService->saveAndAttachAvatar($user, $userDetails);
101 $this->login($user, $remember);
107 * Create a new user from the given ldap credentials and login credentials.
109 * @throws LoginAttemptEmailNeededException
110 * @throws LoginAttemptException
111 * @throws UserRegistrationException
113 protected function createNewFromLdapAndCreds(array $ldapUserDetails, array $credentials): User
115 $email = trim($ldapUserDetails['email'] ?: ($credentials['email'] ?? ''));
118 throw new LoginAttemptEmailNeededException();
122 'name' => $ldapUserDetails['name'],
123 'email' => $ldapUserDetails['email'] ?: $credentials['email'],
124 'external_auth_id' => $ldapUserDetails['uid'],
125 'password' => Str::random(32),
128 $user = $this->registrationService->registerUser($details, null, false);
129 $this->ldapService->saveAndAttachAvatar($user, $ldapUserDetails);