3 namespace BookStack\Access\Guards;
5 use BookStack\Access\LdapService;
6 use BookStack\Access\RegistrationService;
7 use BookStack\Exceptions\JsonDebugException;
8 use BookStack\Exceptions\LdapException;
9 use BookStack\Exceptions\LoginAttemptEmailNeededException;
10 use BookStack\Exceptions\LoginAttemptException;
11 use BookStack\Exceptions\UserRegistrationException;
12 use BookStack\Users\Models\User;
13 use Illuminate\Contracts\Auth\UserProvider;
14 use Illuminate\Contracts\Session\Session;
15 use Illuminate\Support\Str;
17 class LdapSessionGuard extends ExternalBaseSessionGuard
19 protected LdapService $ldapService;
22 * LdapSessionGuard constructor.
24 public function __construct(
26 UserProvider $provider,
28 LdapService $ldapService,
29 RegistrationService $registrationService
31 $this->ldapService = $ldapService;
32 parent::__construct($name, $provider, $session, $registrationService);
36 * Validate a user's credentials.
38 * @param array $credentials
40 * @throws LdapException
44 public function validate(array $credentials = [])
46 $userDetails = $this->ldapService->getUserDetails($credentials['username']);
48 if (isset($userDetails['uid'])) {
49 $this->lastAttempted = $this->provider->retrieveByCredentials([
50 'external_auth_id' => $userDetails['uid'],
54 return $this->ldapService->validateUserCredentials($userDetails, $credentials['password']);
58 * Attempt to authenticate a user using the given credentials.
60 * @param array $credentials
61 * @param bool $remember
63 * @throws LdapException*@throws \BookStack\Exceptions\JsonDebugException
64 * @throws LoginAttemptException
65 * @throws JsonDebugException
69 public function attempt(array $credentials = [], $remember = false)
71 $username = $credentials['username'];
72 $userDetails = $this->ldapService->getUserDetails($username);
75 if (isset($userDetails['uid'])) {
76 $this->lastAttempted = $user = $this->provider->retrieveByCredentials([
77 'external_auth_id' => $userDetails['uid'],
81 if (!$this->ldapService->validateUserCredentials($userDetails, $credentials['password'])) {
87 $user = $this->createNewFromLdapAndCreds($userDetails, $credentials);
88 } catch (UserRegistrationException $exception) {
89 throw new LoginAttemptException($exception->getMessage());
93 // Sync LDAP groups if required
94 if ($this->ldapService->shouldSyncGroups()) {
95 $this->ldapService->syncGroups($user, $username);
98 // Attach avatar if non-existent
99 if (!$user->avatar()->exists()) {
100 $this->ldapService->saveAndAttachAvatar($user, $userDetails);
103 $this->login($user, $remember);
109 * Create a new user from the given ldap credentials and login credentials.
111 * @throws LoginAttemptEmailNeededException
112 * @throws LoginAttemptException
113 * @throws UserRegistrationException
115 protected function createNewFromLdapAndCreds(array $ldapUserDetails, array $credentials): User
117 $email = trim($ldapUserDetails['email'] ?: ($credentials['email'] ?? ''));
120 throw new LoginAttemptEmailNeededException();
124 'name' => $ldapUserDetails['name'],
125 'email' => $ldapUserDetails['email'] ?: $credentials['email'],
126 'external_auth_id' => $ldapUserDetails['uid'],
127 'password' => Str::random(32),
130 $user = $this->registrationService->registerUser($details, null, false);
131 $this->ldapService->saveAndAttachAvatar($user, $ldapUserDetails);