| 
									
										
										
										
											2020-02-01 19:42:22 +08:00
										 |  |  | <?php | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace BookStack\Auth\Access\Guards; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | use BookStack\Auth\Access\LdapService; | 
					
						
							| 
									
										
										
										
											2020-02-03 01:31:00 +08:00
										 |  |  | use BookStack\Auth\Access\RegistrationService; | 
					
						
							| 
									
										
										
										
											2020-02-01 19:42:22 +08:00
										 |  |  | use BookStack\Auth\User; | 
					
						
							| 
									
										
										
										
											2022-03-24 00:34:23 +08:00
										 |  |  | use BookStack\Exceptions\JsonDebugException; | 
					
						
							| 
									
										
										
										
											2020-02-01 19:42:22 +08:00
										 |  |  | use BookStack\Exceptions\LdapException; | 
					
						
							|  |  |  | use BookStack\Exceptions\LoginAttemptEmailNeededException; | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | use BookStack\Exceptions\LoginAttemptException; | 
					
						
							| 
									
										
										
										
											2020-02-03 01:31:00 +08:00
										 |  |  | use BookStack\Exceptions\UserRegistrationException; | 
					
						
							| 
									
										
										
										
											2020-02-01 19:42:22 +08:00
										 |  |  | use Illuminate\Contracts\Auth\UserProvider; | 
					
						
							|  |  |  | use Illuminate\Contracts\Session\Session; | 
					
						
							| 
									
										
										
										
											2020-02-03 01:31:00 +08:00
										 |  |  | use Illuminate\Support\Str; | 
					
						
							| 
									
										
										
										
											2020-02-01 19:42:22 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | class LdapSessionGuard extends ExternalBaseSessionGuard | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2022-03-24 00:34:23 +08:00
										 |  |  |     protected LdapService $ldapService; | 
					
						
							| 
									
										
										
										
											2020-02-01 19:42:22 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * LdapSessionGuard constructor. | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2021-03-08 06:24:05 +08:00
										 |  |  |     public function __construct( | 
					
						
							|  |  |  |         $name, | 
					
						
							| 
									
										
										
										
											2020-02-01 19:42:22 +08:00
										 |  |  |         UserProvider $provider, | 
					
						
							|  |  |  |         Session $session, | 
					
						
							|  |  |  |         LdapService $ldapService, | 
					
						
							| 
									
										
										
										
											2020-02-03 01:31:00 +08:00
										 |  |  |         RegistrationService $registrationService | 
					
						
							| 
									
										
										
										
											2021-03-08 06:24:05 +08:00
										 |  |  |     ) { | 
					
						
							| 
									
										
										
										
											2020-02-01 19:42:22 +08:00
										 |  |  |         $this->ldapService = $ldapService; | 
					
						
							| 
									
										
										
										
											2020-02-03 01:31:00 +08:00
										 |  |  |         parent::__construct($name, $provider, $session, $registrationService); | 
					
						
							| 
									
										
										
										
											2020-02-01 19:42:22 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Validate a user's credentials. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param array $credentials | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2020-02-01 19:42:22 +08:00
										 |  |  |      * @throws LdapException | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |      * | 
					
						
							|  |  |  |      * @return bool | 
					
						
							| 
									
										
										
										
											2020-02-01 19:42:22 +08:00
										 |  |  |      */ | 
					
						
							|  |  |  |     public function validate(array $credentials = []) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $userDetails = $this->ldapService->getUserDetails($credentials['username']); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-15 22:44:36 +08:00
										 |  |  |         if (isset($userDetails['uid'])) { | 
					
						
							|  |  |  |             $this->lastAttempted = $this->provider->retrieveByCredentials([ | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |                 'external_auth_id' => $userDetails['uid'], | 
					
						
							| 
									
										
										
										
											2020-02-15 22:44:36 +08:00
										 |  |  |             ]); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         return $this->ldapService->validateUserCredentials($userDetails, $credentials['password']); | 
					
						
							| 
									
										
										
										
											2020-02-01 19:42:22 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * Attempt to authenticate a user using the given credentials. | 
					
						
							|  |  |  |      * | 
					
						
							|  |  |  |      * @param array $credentials | 
					
						
							| 
									
										
										
										
											2022-03-25 19:14:27 +08:00
										 |  |  |      * @param bool  $remember | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |      * | 
					
						
							| 
									
										
										
										
											2022-03-24 00:34:23 +08:00
										 |  |  |      * @throws LdapException*@throws \BookStack\Exceptions\JsonDebugException | 
					
						
							|  |  |  |      * @throws LoginAttemptException | 
					
						
							|  |  |  |      * @throws JsonDebugException | 
					
						
							| 
									
										
										
										
											2022-03-25 19:14:27 +08:00
										 |  |  |      * | 
					
						
							|  |  |  |      * @return bool | 
					
						
							| 
									
										
										
										
											2020-02-01 19:42:22 +08:00
										 |  |  |      */ | 
					
						
							|  |  |  |     public function attempt(array $credentials = [], $remember = false) | 
					
						
							|  |  |  |     { | 
					
						
							|  |  |  |         $username = $credentials['username']; | 
					
						
							|  |  |  |         $userDetails = $this->ldapService->getUserDetails($username); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-15 22:44:36 +08:00
										 |  |  |         $user = null; | 
					
						
							|  |  |  |         if (isset($userDetails['uid'])) { | 
					
						
							|  |  |  |             $this->lastAttempted = $user = $this->provider->retrieveByCredentials([ | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |                 'external_auth_id' => $userDetails['uid'], | 
					
						
							| 
									
										
										
										
											2020-02-15 22:44:36 +08:00
										 |  |  |             ]); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (!$this->ldapService->validateUserCredentials($userDetails, $credentials['password'])) { | 
					
						
							| 
									
										
										
										
											2020-02-01 19:42:22 +08:00
										 |  |  |             return false; | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |         if (is_null($user)) { | 
					
						
							| 
									
										
										
										
											2020-04-26 19:13:00 +08:00
										 |  |  |             try { | 
					
						
							|  |  |  |                 $user = $this->createNewFromLdapAndCreds($userDetails, $credentials); | 
					
						
							|  |  |  |             } catch (UserRegistrationException $exception) { | 
					
						
							| 
									
										
										
										
											2022-02-04 08:26:19 +08:00
										 |  |  |                 throw new LoginAttemptException($exception->getMessage()); | 
					
						
							| 
									
										
										
										
											2020-04-26 19:13:00 +08:00
										 |  |  |             } | 
					
						
							| 
									
										
										
										
											2020-02-01 19:42:22 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-01 22:30:23 +08:00
										 |  |  |         // Sync LDAP groups if required
 | 
					
						
							|  |  |  |         if ($this->ldapService->shouldSyncGroups()) { | 
					
						
							|  |  |  |             $this->ldapService->syncGroups($user, $username); | 
					
						
							| 
									
										
										
										
											2020-02-01 19:42:22 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2021-05-25 01:45:08 +08:00
										 |  |  |         // Attach avatar if non-existent
 | 
					
						
							| 
									
										
										
										
											2021-11-06 08:32:01 +08:00
										 |  |  |         if (!$user->avatar()->exists()) { | 
					
						
							| 
									
										
										
										
											2021-05-25 01:45:08 +08:00
										 |  |  |             $this->ldapService->saveAndAttachAvatar($user, $userDetails); | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-01 22:30:23 +08:00
										 |  |  |         $this->login($user, $remember); | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-01 22:30:23 +08:00
										 |  |  |         return true; | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2020-02-01 19:42:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-01 22:30:23 +08:00
										 |  |  |     /** | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |      * Create a new user from the given ldap credentials and login credentials. | 
					
						
							|  |  |  |      * | 
					
						
							| 
									
										
										
										
											2020-02-03 01:31:00 +08:00
										 |  |  |      * @throws LoginAttemptEmailNeededException | 
					
						
							| 
									
										
										
										
											2020-02-01 22:30:23 +08:00
										 |  |  |      * @throws LoginAttemptException | 
					
						
							| 
									
										
										
										
											2020-02-03 01:31:00 +08:00
										 |  |  |      * @throws UserRegistrationException | 
					
						
							| 
									
										
										
										
											2020-02-01 22:30:23 +08:00
										 |  |  |      */ | 
					
						
							| 
									
										
										
										
											2020-02-03 01:31:00 +08:00
										 |  |  |     protected function createNewFromLdapAndCreds(array $ldapUserDetails, array $credentials): User | 
					
						
							| 
									
										
										
										
											2020-02-01 22:30:23 +08:00
										 |  |  |     { | 
					
						
							| 
									
										
										
										
											2020-02-03 01:31:00 +08:00
										 |  |  |         $email = trim($ldapUserDetails['email'] ?: ($credentials['email'] ?? '')); | 
					
						
							| 
									
										
										
										
											2020-02-01 19:42:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-03 01:31:00 +08:00
										 |  |  |         if (empty($email)) { | 
					
						
							| 
									
										
										
										
											2020-02-01 22:30:23 +08:00
										 |  |  |             throw new LoginAttemptEmailNeededException(); | 
					
						
							| 
									
										
										
										
											2020-02-01 19:42:22 +08:00
										 |  |  |         } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-02-03 01:31:00 +08:00
										 |  |  |         $details = [ | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |             'name'             => $ldapUserDetails['name'], | 
					
						
							|  |  |  |             'email'            => $ldapUserDetails['email'] ?: $credentials['email'], | 
					
						
							| 
									
										
										
										
											2020-02-03 01:31:00 +08:00
										 |  |  |             'external_auth_id' => $ldapUserDetails['uid'], | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  |             'password'         => Str::random(32), | 
					
						
							| 
									
										
										
										
											2020-02-03 01:31:00 +08:00
										 |  |  |         ]; | 
					
						
							| 
									
										
										
										
											2020-02-01 19:42:22 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-13 00:33:55 +08:00
										 |  |  |         $user = $this->registrationService->registerUser($details, null, false); | 
					
						
							| 
									
										
										
										
											2021-05-25 01:45:08 +08:00
										 |  |  |         $this->ldapService->saveAndAttachAvatar($user, $ldapUserDetails); | 
					
						
							| 
									
										
										
										
											2021-06-26 23:23:15 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2020-10-13 00:33:55 +08:00
										 |  |  |         return $user; | 
					
						
							| 
									
										
										
										
											2020-02-01 19:42:22 +08:00
										 |  |  |     } | 
					
						
							|  |  |  | } |