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