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\Auth\UserRepo;
9 use BookStack\Exceptions\LdapException;
10 use BookStack\Exceptions\LoginAttemptException;
11 use BookStack\Exceptions\LoginAttemptEmailNeededException;
12 use BookStack\Exceptions\UserRegistrationException;
13 use Illuminate\Contracts\Auth\UserProvider;
14 use Illuminate\Contracts\Session\Session;
15 use Illuminate\Support\Facades\Hash;
16 use Illuminate\Support\Str;
18 class LdapSessionGuard extends ExternalBaseSessionGuard
21 protected $ldapService;
24 * LdapSessionGuard constructor.
26 public function __construct($name,
27 UserProvider $provider,
29 LdapService $ldapService,
30 RegistrationService $registrationService
33 $this->ldapService = $ldapService;
34 parent::__construct($name, $provider, $session, $registrationService);
38 * Validate a user's credentials.
40 * @param array $credentials
42 * @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 LoginAttemptException
64 * @throws LdapException
66 public function attempt(array $credentials = [], $remember = false)
68 $username = $credentials['username'];
69 $userDetails = $this->ldapService->getUserDetails($username);
72 if (isset($userDetails['uid'])) {
73 $this->lastAttempted = $user = $this->provider->retrieveByCredentials([
74 'external_auth_id' => $userDetails['uid']
78 if (!$this->ldapService->validateUserCredentials($userDetails, $credentials['password'])) {
84 $user = $this->createNewFromLdapAndCreds($userDetails, $credentials);
85 } catch (UserRegistrationException $exception) {
86 throw new LoginAttemptException($exception->message);
90 // Sync LDAP groups if required
91 if ($this->ldapService->shouldSyncGroups()) {
92 $this->ldapService->syncGroups($user, $username);
95 $this->login($user, $remember);
100 * Create a new user from the given ldap credentials and login credentials
101 * @throws LoginAttemptEmailNeededException
102 * @throws LoginAttemptException
103 * @throws UserRegistrationException
105 protected function createNewFromLdapAndCreds(array $ldapUserDetails, array $credentials): User
107 $email = trim($ldapUserDetails['email'] ?: ($credentials['email'] ?? ''));
110 throw new LoginAttemptEmailNeededException();
114 'name' => $ldapUserDetails['name'],
115 'email' => $ldapUserDetails['email'] ?: $credentials['email'],
116 'external_auth_id' => $ldapUserDetails['uid'],
117 'password' => Str::random(32),
120 $user = $this->registrationService->registerUser($details, null, false);
122 if (config('services.ldap.import_thumbnail_photos')) {
123 $imageService = app()->make(ImageService::class);
124 $image = $imageService->saveNewFromBase64Uri('data:image/jpg;base64,'.base64_encode($ldapUserDetails['avatar']), $ldapUserDetails['uid'].'.jpg', 'user');
126 $user['image_id'] = $image->id;