]> BookStack Code Mirror - bookstack/blob - app/Auth/Access/Guards/LdapSessionGuard.php
Merge branch 'master' of https://github.com/jasonhoule/BookStack into jasonhoule...
[bookstack] / app / Auth / Access / Guards / LdapSessionGuard.php
1 <?php
2
3 namespace BookStack\Auth\Access\Guards;
4
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\LoginAttemptException;
10 use BookStack\Exceptions\LoginAttemptEmailNeededException;
11 use BookStack\Exceptions\UserRegistrationException;
12 use Illuminate\Contracts\Auth\UserProvider;
13 use Illuminate\Contracts\Session\Session;
14 use Illuminate\Support\Str;
15
16 class LdapSessionGuard extends ExternalBaseSessionGuard
17 {
18
19     protected $ldapService;
20
21     /**
22      * LdapSessionGuard constructor.
23      */
24     public function __construct(
25         $name,
26         UserProvider $provider,
27         Session $session,
28         LdapService $ldapService,
29         RegistrationService $registrationService
30     ) {
31         $this->ldapService = $ldapService;
32         parent::__construct($name, $provider, $session, $registrationService);
33     }
34
35     /**
36      * Validate a user's credentials.
37      *
38      * @param array $credentials
39      * @return bool
40      * @throws LdapException
41      */
42     public function validate(array $credentials = [])
43     {
44         $userDetails = $this->ldapService->getUserDetails($credentials['username']);
45
46         if (isset($userDetails['uid'])) {
47             $this->lastAttempted = $this->provider->retrieveByCredentials([
48                 'external_auth_id' => $userDetails['uid']
49             ]);
50         }
51
52         return $this->ldapService->validateUserCredentials($userDetails, $credentials['password']);
53     }
54
55     /**
56      * Attempt to authenticate a user using the given credentials.
57      *
58      * @param array $credentials
59      * @param bool $remember
60      * @return bool
61      * @throws LoginAttemptException
62      * @throws LdapException
63      */
64     public function attempt(array $credentials = [], $remember = false)
65     {
66         $username = $credentials['username'];
67         $userDetails = $this->ldapService->getUserDetails($username);
68
69         $user = null;
70         if (isset($userDetails['uid'])) {
71             $this->lastAttempted = $user = $this->provider->retrieveByCredentials([
72                 'external_auth_id' => $userDetails['uid']
73             ]);
74         }
75
76         if (!$this->ldapService->validateUserCredentials($userDetails, $credentials['password'])) {
77             return false;
78         }
79
80         if (is_null($user)) {
81             try {
82                 $user = $this->createNewFromLdapAndCreds($userDetails, $credentials);
83             } catch (UserRegistrationException $exception) {
84                 throw new LoginAttemptException($exception->message);
85             }
86         }
87
88         // Sync LDAP groups if required
89         if ($this->ldapService->shouldSyncGroups()) {
90             $this->ldapService->syncGroups($user, $username);
91         }
92
93         $this->login($user, $remember);
94         return true;
95     }
96
97     /**
98      * Create a new user from the given ldap credentials and login credentials
99      * @throws LoginAttemptEmailNeededException
100      * @throws LoginAttemptException
101      * @throws UserRegistrationException
102      */
103     protected function createNewFromLdapAndCreds(array $ldapUserDetails, array $credentials): User
104     {
105         $email = trim($ldapUserDetails['email'] ?: ($credentials['email'] ?? ''));
106
107         if (empty($email)) {
108             throw new LoginAttemptEmailNeededException();
109         }
110
111         $details = [
112             'name' => $ldapUserDetails['name'],
113             'email' => $ldapUserDetails['email'] ?: $credentials['email'],
114             'external_auth_id' => $ldapUserDetails['uid'],
115             'password' => Str::random(32),
116         ];
117
118         $user = $this->registrationService->registerUser($details, null, false);
119
120         if (config('services.ldap.import_thumbnail_photos')) {
121             $imageService = app()->make(ImageService::class);
122             $image = $imageService->saveNewFromBase64Uri('data:image/jpg;base64,'.base64_encode($ldapUserDetails['avatar']), $ldapUserDetails['uid'].'.jpg', 'user');
123
124             $user['image_id'] = $image->id;
125             $user->save();
126         }
127
128         return $user;
129     }
130 }