Authentication backends refactoring
This commit is contained in:
parent
498408d507
commit
925b0ba2e5
|
|
@ -0,0 +1,60 @@
|
|||
<?php
|
||||
|
||||
namespace Auth;
|
||||
|
||||
use Core\Tool;
|
||||
use Core\Registry;
|
||||
use PicoDb\Database;
|
||||
|
||||
/**
|
||||
* Base auth class
|
||||
*
|
||||
* @package auth
|
||||
* @author Frederic Guillot
|
||||
*
|
||||
* @property \Model\Acl $acl
|
||||
* @property \Model\LastLogin $lastLogin
|
||||
* @property \Model\User $user
|
||||
*/
|
||||
abstract class Base
|
||||
{
|
||||
/**
|
||||
* Database instance
|
||||
*
|
||||
* @access protected
|
||||
* @var \PicoDb\Database
|
||||
*/
|
||||
protected $db;
|
||||
|
||||
/**
|
||||
* Registry instance
|
||||
*
|
||||
* @access protected
|
||||
* @var \Core\Registry
|
||||
*/
|
||||
protected $registry;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*
|
||||
* @access public
|
||||
* @param \Core\Registry $registry Registry instance
|
||||
*/
|
||||
public function __construct(Registry $registry)
|
||||
{
|
||||
$this->registry = $registry;
|
||||
$this->db = $this->registry->shared('db');
|
||||
}
|
||||
|
||||
/**
|
||||
* Load automatically models
|
||||
*
|
||||
* @access public
|
||||
* @param string $name Model name
|
||||
* @return mixed
|
||||
*/
|
||||
public function __get($name)
|
||||
{
|
||||
return Tool::loadModel($this->registry, $name);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,52 @@
|
|||
<?php
|
||||
|
||||
namespace Auth;
|
||||
|
||||
use Model\User;
|
||||
|
||||
/**
|
||||
* Database authentication
|
||||
*
|
||||
* @package auth
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Database extends Base
|
||||
{
|
||||
/**
|
||||
* Backend name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const AUTH_NAME = 'Database';
|
||||
|
||||
/**
|
||||
* Authenticate a user
|
||||
*
|
||||
* @access public
|
||||
* @param string $username Username
|
||||
* @param string $password Password
|
||||
* @return boolean
|
||||
*/
|
||||
public function authenticate($username, $password)
|
||||
{
|
||||
$user = $this->db->table(User::TABLE)->eq('username', $username)->eq('is_ldap_user', 0)->findOne();
|
||||
|
||||
if ($user && password_verify($password, $user['password'])) {
|
||||
|
||||
// Update user session
|
||||
$this->user->updateSession($user);
|
||||
|
||||
// Update login history
|
||||
$this->lastLogin->create(
|
||||
self::AUTH_NAME,
|
||||
$user['id'],
|
||||
$this->user->getIpAddress(),
|
||||
$this->user->getUserAgent()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,171 +1,178 @@
|
|||
<?php
|
||||
|
||||
namespace Model;
|
||||
|
||||
require __DIR__.'/../../vendor/OAuth/bootstrap.php';
|
||||
|
||||
use OAuth\Common\Storage\Session;
|
||||
use OAuth\Common\Consumer\Credentials;
|
||||
use OAuth\Common\Http\Uri\UriFactory;
|
||||
use OAuth\ServiceFactory;
|
||||
use OAuth\Common\Http\Exception\TokenResponseException;
|
||||
|
||||
/**
|
||||
* GitHub model
|
||||
*
|
||||
* @package model
|
||||
*/
|
||||
class GitHub extends Base
|
||||
{
|
||||
/**
|
||||
* Authenticate a GitHub user
|
||||
*
|
||||
* @access public
|
||||
* @param string $github_id GitHub user id
|
||||
* @return boolean
|
||||
*/
|
||||
public function authenticate($github_id)
|
||||
{
|
||||
$user = $this->user->getByGitHubId($github_id);
|
||||
|
||||
if ($user) {
|
||||
|
||||
// Create the user session
|
||||
$this->user->updateSession($user);
|
||||
|
||||
// Update login history
|
||||
$this->lastLogin->create(
|
||||
LastLogin::AUTH_GITHUB,
|
||||
$user['id'],
|
||||
$this->user->getIpAddress(),
|
||||
$this->user->getUserAgent()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink a GitHub account for a given user
|
||||
*
|
||||
* @access public
|
||||
* @param integer $user_id User id
|
||||
* @return boolean
|
||||
*/
|
||||
public function unlink($user_id)
|
||||
{
|
||||
return $this->user->update(array(
|
||||
'id' => $user_id,
|
||||
'github_id' => '',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the user table based on the GitHub profile information
|
||||
*
|
||||
* @access public
|
||||
* @param integer $user_id User id
|
||||
* @param array $profile GitHub profile
|
||||
* @return boolean
|
||||
* @todo Don't overwrite existing email/name with empty GitHub data
|
||||
*/
|
||||
public function updateUser($user_id, array $profile)
|
||||
{
|
||||
return $this->user->update(array(
|
||||
'id' => $user_id,
|
||||
'github_id' => $profile['id'],
|
||||
'email' => $profile['email'],
|
||||
'name' => $profile['name'],
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the GitHub service instance
|
||||
*
|
||||
* @access public
|
||||
* @return \OAuth\OAuth2\Service\GitHub
|
||||
*/
|
||||
public function getService()
|
||||
{
|
||||
$uriFactory = new UriFactory();
|
||||
$currentUri = $uriFactory->createFromSuperGlobalArray($_SERVER);
|
||||
$currentUri->setQuery('controller=user&action=gitHub');
|
||||
|
||||
$storage = new Session(false);
|
||||
|
||||
$credentials = new Credentials(
|
||||
GITHUB_CLIENT_ID,
|
||||
GITHUB_CLIENT_SECRET,
|
||||
$currentUri->getAbsoluteUri()
|
||||
);
|
||||
|
||||
$serviceFactory = new ServiceFactory();
|
||||
|
||||
return $serviceFactory->createService(
|
||||
'gitHub',
|
||||
$credentials,
|
||||
$storage,
|
||||
array('')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the authorization URL
|
||||
*
|
||||
* @access public
|
||||
* @return \OAuth\Common\Http\Uri\Uri
|
||||
*/
|
||||
public function getAuthorizationUrl()
|
||||
{
|
||||
return $this->getService()->getAuthorizationUri();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get GitHub profile information from the API
|
||||
*
|
||||
* @access public
|
||||
* @param string $code GitHub authorization code
|
||||
* @return bool|array
|
||||
*/
|
||||
public function getGitHubProfile($code)
|
||||
{
|
||||
try {
|
||||
$gitHubService = $this->getService();
|
||||
$gitHubService->requestAccessToken($code);
|
||||
|
||||
return json_decode($gitHubService->request('user'), true);
|
||||
}
|
||||
catch (TokenResponseException $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Revokes this user's GitHub tokens for Kanboard
|
||||
*
|
||||
* @access public
|
||||
* @return bool|array
|
||||
* @todo Currently this simply removes all our tokens for this user, ideally it should
|
||||
* restrict itself to the one in question
|
||||
*/
|
||||
public function revokeGitHubAccess()
|
||||
{
|
||||
try {
|
||||
$gitHubService = $this->getService();
|
||||
|
||||
$basicAuthHeader = array('Authorization' => 'Basic ' .
|
||||
base64_encode(GITHUB_CLIENT_ID.':'.GITHUB_CLIENT_SECRET));
|
||||
|
||||
return json_decode($gitHubService->request('/applications/'.GITHUB_CLIENT_ID.'/tokens', 'DELETE', null, $basicAuthHeader), true);
|
||||
}
|
||||
catch (TokenResponseException $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
<?php
|
||||
|
||||
namespace Auth;
|
||||
|
||||
require __DIR__.'/../../vendor/OAuth/bootstrap.php';
|
||||
|
||||
use OAuth\Common\Storage\Session;
|
||||
use OAuth\Common\Consumer\Credentials;
|
||||
use OAuth\Common\Http\Uri\UriFactory;
|
||||
use OAuth\ServiceFactory;
|
||||
use OAuth\Common\Http\Exception\TokenResponseException;
|
||||
|
||||
/**
|
||||
* GitHub backend
|
||||
*
|
||||
* @package auth
|
||||
*/
|
||||
class GitHub extends Base
|
||||
{
|
||||
/**
|
||||
* Backend name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const AUTH_NAME = 'Github';
|
||||
|
||||
/**
|
||||
* Authenticate a GitHub user
|
||||
*
|
||||
* @access public
|
||||
* @param string $github_id GitHub user id
|
||||
* @return boolean
|
||||
*/
|
||||
public function authenticate($github_id)
|
||||
{
|
||||
$user = $this->user->getByGitHubId($github_id);
|
||||
|
||||
if ($user) {
|
||||
|
||||
// Create the user session
|
||||
$this->user->updateSession($user);
|
||||
|
||||
// Update login history
|
||||
$this->lastLogin->create(
|
||||
self::AUTH_NAME,
|
||||
$user['id'],
|
||||
$this->user->getIpAddress(),
|
||||
$this->user->getUserAgent()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Unlink a GitHub account for a given user
|
||||
*
|
||||
* @access public
|
||||
* @param integer $user_id User id
|
||||
* @return boolean
|
||||
*/
|
||||
public function unlink($user_id)
|
||||
{
|
||||
return $this->user->update(array(
|
||||
'id' => $user_id,
|
||||
'github_id' => '',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the user table based on the GitHub profile information
|
||||
*
|
||||
* @access public
|
||||
* @param integer $user_id User id
|
||||
* @param array $profile GitHub profile
|
||||
* @return boolean
|
||||
* @todo Don't overwrite existing email/name with empty GitHub data
|
||||
*/
|
||||
public function updateUser($user_id, array $profile)
|
||||
{
|
||||
return $this->user->update(array(
|
||||
'id' => $user_id,
|
||||
'github_id' => $profile['id'],
|
||||
'email' => $profile['email'],
|
||||
'name' => $profile['name'],
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the GitHub service instance
|
||||
*
|
||||
* @access public
|
||||
* @return \OAuth\OAuth2\Service\GitHub
|
||||
*/
|
||||
public function getService()
|
||||
{
|
||||
$uriFactory = new UriFactory();
|
||||
$currentUri = $uriFactory->createFromSuperGlobalArray($_SERVER);
|
||||
$currentUri->setQuery('controller=user&action=gitHub');
|
||||
|
||||
$storage = new Session(false);
|
||||
|
||||
$credentials = new Credentials(
|
||||
GITHUB_CLIENT_ID,
|
||||
GITHUB_CLIENT_SECRET,
|
||||
$currentUri->getAbsoluteUri()
|
||||
);
|
||||
|
||||
$serviceFactory = new ServiceFactory();
|
||||
|
||||
return $serviceFactory->createService(
|
||||
'gitHub',
|
||||
$credentials,
|
||||
$storage,
|
||||
array('')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the authorization URL
|
||||
*
|
||||
* @access public
|
||||
* @return \OAuth\Common\Http\Uri\Uri
|
||||
*/
|
||||
public function getAuthorizationUrl()
|
||||
{
|
||||
return $this->getService()->getAuthorizationUri();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get GitHub profile information from the API
|
||||
*
|
||||
* @access public
|
||||
* @param string $code GitHub authorization code
|
||||
* @return bool|array
|
||||
*/
|
||||
public function getGitHubProfile($code)
|
||||
{
|
||||
try {
|
||||
$gitHubService = $this->getService();
|
||||
$gitHubService->requestAccessToken($code);
|
||||
|
||||
return json_decode($gitHubService->request('user'), true);
|
||||
}
|
||||
catch (TokenResponseException $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Revokes this user's GitHub tokens for Kanboard
|
||||
*
|
||||
* @access public
|
||||
* @return bool|array
|
||||
* @todo Currently this simply removes all our tokens for this user, ideally it should
|
||||
* restrict itself to the one in question
|
||||
*/
|
||||
public function revokeGitHubAccess()
|
||||
{
|
||||
try {
|
||||
$gitHubService = $this->getService();
|
||||
|
||||
$basicAuthHeader = array('Authorization' => 'Basic ' .
|
||||
base64_encode(GITHUB_CLIENT_ID.':'.GITHUB_CLIENT_SECRET));
|
||||
|
||||
return json_decode($gitHubService->request('/applications/'.GITHUB_CLIENT_ID.'/tokens', 'DELETE', null, $basicAuthHeader), true);
|
||||
}
|
||||
catch (TokenResponseException $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
<?php
|
||||
|
||||
namespace Model;
|
||||
namespace Auth;
|
||||
|
||||
require __DIR__.'/../../vendor/OAuth/bootstrap.php';
|
||||
|
||||
|
|
@ -11,13 +11,20 @@ use OAuth\ServiceFactory;
|
|||
use OAuth\Common\Http\Exception\TokenResponseException;
|
||||
|
||||
/**
|
||||
* Google model
|
||||
* Google backend
|
||||
*
|
||||
* @package model
|
||||
* @package auth
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Google extends Base
|
||||
{
|
||||
/**
|
||||
* Backend name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const AUTH_NAME = 'Google';
|
||||
|
||||
/**
|
||||
* Authenticate a Google user
|
||||
*
|
||||
|
|
@ -36,7 +43,7 @@ class Google extends Base
|
|||
|
||||
// Update login history
|
||||
$this->lastLogin->create(
|
||||
LastLogin::AUTH_GOOGLE,
|
||||
self::AUTH_NAME,
|
||||
$user['id'],
|
||||
$this->user->getIpAddress(),
|
||||
$this->user->getUserAgent()
|
||||
|
|
@ -0,0 +1,150 @@
|
|||
<?php
|
||||
|
||||
namespace Auth;
|
||||
|
||||
/**
|
||||
* LDAP model
|
||||
*
|
||||
* @package auth
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Ldap extends Base
|
||||
{
|
||||
/**
|
||||
* Backend name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const AUTH_NAME = 'LDAP';
|
||||
|
||||
/**
|
||||
* Authenticate the user
|
||||
*
|
||||
* @access public
|
||||
* @param string $username Username
|
||||
* @param string $password Password
|
||||
* @return boolean
|
||||
*/
|
||||
public function authenticate($username, $password)
|
||||
{
|
||||
$result = $this->findUser($username, $password);
|
||||
|
||||
if (is_array($result)) {
|
||||
|
||||
$user = $this->user->getByUsername($username);
|
||||
|
||||
if ($user) {
|
||||
|
||||
// There is already a local user with that name
|
||||
if ($user['is_ldap_user'] == 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
// We create automatically a new user
|
||||
if ($this->createUser($username, $result['name'], $result['email'])) {
|
||||
$user = $this->user->getByUsername($username);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// We open the session
|
||||
$this->user->updateSession($user);
|
||||
|
||||
// Update login history
|
||||
$this->lastLogin->create(
|
||||
self::AUTH_NAME,
|
||||
$user['id'],
|
||||
$this->user->getIpAddress(),
|
||||
$this->user->getUserAgent()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the user from the LDAP server
|
||||
*
|
||||
* @access public
|
||||
* @param string $username Username
|
||||
* @param string $password Password
|
||||
* @return boolean|array
|
||||
*/
|
||||
public function findUser($username, $password)
|
||||
{
|
||||
if (! function_exists('ldap_connect')) {
|
||||
die('The PHP LDAP extension is required');
|
||||
}
|
||||
|
||||
// Skip SSL certificate verification
|
||||
if (! LDAP_SSL_VERIFY) {
|
||||
putenv('LDAPTLS_REQCERT=never');
|
||||
}
|
||||
|
||||
$ldap = ldap_connect(LDAP_SERVER, LDAP_PORT);
|
||||
|
||||
if (! is_resource($ldap)) {
|
||||
die('Unable to connect to the LDAP server: "'.LDAP_SERVER.'"');
|
||||
}
|
||||
|
||||
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
|
||||
|
||||
if (! @ldap_bind($ldap, LDAP_USERNAME, LDAP_PASSWORD)) {
|
||||
die('Unable to bind to the LDAP server: "'.LDAP_SERVER.'"');
|
||||
}
|
||||
|
||||
$sr = @ldap_search($ldap, LDAP_ACCOUNT_BASE, sprintf(LDAP_USER_PATTERN, $username), array(LDAP_ACCOUNT_FULLNAME, LDAP_ACCOUNT_EMAIL));
|
||||
|
||||
if ($sr === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$info = ldap_get_entries($ldap, $sr);
|
||||
|
||||
// User not found
|
||||
if (count($info) == 0 || $info['count'] == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We got our user
|
||||
if (@ldap_bind($ldap, $info[0]['dn'], $password)) {
|
||||
|
||||
return array(
|
||||
'username' => $username,
|
||||
'name' => isset($info[0][LDAP_ACCOUNT_FULLNAME][0]) ? $info[0][LDAP_ACCOUNT_FULLNAME][0] : '',
|
||||
'email' => isset($info[0][LDAP_ACCOUNT_EMAIL][0]) ? $info[0][LDAP_ACCOUNT_EMAIL][0] : '',
|
||||
);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new local user after the LDAP authentication
|
||||
*
|
||||
* @access public
|
||||
* @param string $username Username
|
||||
* @param string $name Name of the user
|
||||
* @param string $email Email address
|
||||
* @return bool
|
||||
*/
|
||||
public function createUser($username, $name, $email)
|
||||
{
|
||||
$values = array(
|
||||
'username' => $username,
|
||||
'name' => $name,
|
||||
'email' => $email,
|
||||
'is_admin' => 0,
|
||||
'is_ldap_user' => 1,
|
||||
);
|
||||
|
||||
return $this->user->create($values);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Model;
|
||||
namespace Auth;
|
||||
|
||||
use Core\Security;
|
||||
|
||||
/**
|
||||
* RememberMe model
|
||||
*
|
||||
* @package model
|
||||
* @package auth
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class RememberMe extends Base
|
||||
{
|
||||
/**
|
||||
* Backend name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const AUTH_NAME = 'RememberMe';
|
||||
|
||||
/**
|
||||
* SQL table name
|
||||
*
|
||||
|
|
@ -95,6 +102,14 @@ class RememberMe extends Base
|
|||
$this->user->updateSession($this->user->getById($record['user_id']));
|
||||
$this->acl->isRememberMe(true);
|
||||
|
||||
// Update last login infos
|
||||
$this->lastLogin->create(
|
||||
self::AUTH_NAME,
|
||||
$this->acl->getUserId(),
|
||||
$this->user->getIpAddress(),
|
||||
$this->user->getUserAgent()
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,17 +1,24 @@
|
|||
<?php
|
||||
|
||||
namespace Model;
|
||||
namespace Auth;
|
||||
|
||||
use Core\Security;
|
||||
|
||||
/**
|
||||
* ReverseProxyAuth model
|
||||
* ReverseProxy backend
|
||||
*
|
||||
* @package model
|
||||
* @package auth
|
||||
* @author Sylvain Veyrié
|
||||
*/
|
||||
class ReverseProxyAuth extends Base
|
||||
class ReverseProxy extends Base
|
||||
{
|
||||
/**
|
||||
* Backend name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const AUTH_NAME = 'ReverseProxy';
|
||||
|
||||
/**
|
||||
* Authenticate the user with the HTTP header
|
||||
*
|
||||
|
|
@ -35,7 +42,7 @@ class ReverseProxyAuth extends Base
|
|||
|
||||
// Update login history
|
||||
$this->lastLogin->create(
|
||||
LastLogin::AUTH_REVERSE_PROXY,
|
||||
self::AUTH_NAME,
|
||||
$user['id'],
|
||||
$this->user->getIpAddress(),
|
||||
$this->user->getUserAgent()
|
||||
|
|
@ -15,20 +15,16 @@ use Model\LastLogin;
|
|||
* @author Frederic Guillot
|
||||
*
|
||||
* @property \Model\Acl $acl
|
||||
* @property \Model\Authentication $authentication
|
||||
* @property \Model\Action $action
|
||||
* @property \Model\Board $board
|
||||
* @property \Model\Category $category
|
||||
* @property \Model\Comment $comment
|
||||
* @property \Model\Config $config
|
||||
* @property \Model\File $file
|
||||
* @property \Model\Google $google
|
||||
* @property \Model\GitHub $gitHub
|
||||
* @property \Model\LastLogin $lastLogin
|
||||
* @property \Model\Ldap $ldap
|
||||
* @property \Model\Notification $notification
|
||||
* @property \Model\Project $project
|
||||
* @property \Model\RememberMe $rememberMe
|
||||
* @property \Model\ReverseProxyAuth $reverseProxyAuth
|
||||
* @property \Model\SubTask $subTask
|
||||
* @property \Model\Task $task
|
||||
* @property \Model\User $user
|
||||
|
|
@ -123,29 +119,8 @@ abstract class Base
|
|||
date_default_timezone_set($this->config->get('timezone', 'UTC'));
|
||||
|
||||
// Authentication
|
||||
if (! $this->acl->isLogged() && ! $this->acl->isPublicAction($controller, $action)) {
|
||||
|
||||
// Try the "remember me" authentication first
|
||||
if (! $this->rememberMe->authenticate()) {
|
||||
|
||||
// Automatic reverse proxy header authentication
|
||||
if(! (REVERSE_PROXY_AUTH && $this->reverseProxyAuth->authenticate()) ) {
|
||||
// Redirect to the login form if not authenticated
|
||||
$this->response->redirect('?controller=user&action=login');
|
||||
}
|
||||
}
|
||||
else {
|
||||
|
||||
$this->lastLogin->create(
|
||||
LastLogin::AUTH_REMEMBER_ME,
|
||||
$this->acl->getUserId(),
|
||||
$this->user->getIpAddress(),
|
||||
$this->user->getUserAgent()
|
||||
);
|
||||
}
|
||||
}
|
||||
else if ($this->rememberMe->hasCookie()) {
|
||||
$this->rememberMe->refresh();
|
||||
if (! $this->authentication->isAuthenticated($controller, $action)) {
|
||||
$this->response->redirect('?controller=user&action=login');
|
||||
}
|
||||
|
||||
// Check if the user is allowed to see this page
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ class Config extends Base
|
|||
'menu' => 'config',
|
||||
'title' => t('Settings'),
|
||||
'timezones' => $this->config->getTimezones(),
|
||||
'remember_me_sessions' => $this->rememberMe->getAll($this->acl->getUserId()),
|
||||
'remember_me_sessions' => $this->authentication->backend('rememberMe')->getAll($this->acl->getUserId()),
|
||||
'last_logins' => $this->lastLogin->getAll($this->acl->getUserId()),
|
||||
)));
|
||||
}
|
||||
|
|
@ -73,7 +73,7 @@ class Config extends Base
|
|||
'menu' => 'config',
|
||||
'title' => t('Settings'),
|
||||
'timezones' => $this->config->getTimezones(),
|
||||
'remember_me_sessions' => $this->rememberMe->getAll($this->acl->getUserId()),
|
||||
'remember_me_sessions' => $this->authentication->backend('rememberMe')->getAll($this->acl->getUserId()),
|
||||
'last_logins' => $this->lastLogin->getAll($this->acl->getUserId()),
|
||||
)));
|
||||
}
|
||||
|
|
@ -124,7 +124,7 @@ class Config extends Base
|
|||
public function removeRememberMeToken()
|
||||
{
|
||||
$this->checkCSRFParam();
|
||||
$this->rememberMe->remove($this->request->getIntegerParam('id'));
|
||||
$this->authentication->backend('rememberMe')->remove($this->request->getIntegerParam('id'));
|
||||
$this->response->redirect('?controller=config&action=index#remember-me');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ class User extends Base
|
|||
public function logout()
|
||||
{
|
||||
$this->checkCSRFParam();
|
||||
$this->rememberMe->destroy($this->acl->getUserId());
|
||||
$this->authentication->backend('rememberMe')->destroy($this->acl->getUserId());
|
||||
$this->session->close();
|
||||
$this->response->redirect('?controller=user&action=login');
|
||||
}
|
||||
|
|
@ -30,7 +30,7 @@ class User extends Base
|
|||
*/
|
||||
public function login()
|
||||
{
|
||||
if (isset($_SESSION['user'])) {
|
||||
if ($this->acl->isLogged()) {
|
||||
$this->response->redirect('?controller=app');
|
||||
}
|
||||
|
||||
|
|
@ -50,7 +50,7 @@ class User extends Base
|
|||
public function check()
|
||||
{
|
||||
$values = $this->request->getValues();
|
||||
list($valid, $errors) = $this->user->validateLogin($values);
|
||||
list($valid, $errors) = $this->authentication->validateForm($values);
|
||||
|
||||
if ($valid) {
|
||||
$this->response->redirect('?controller=app');
|
||||
|
|
@ -249,14 +249,14 @@ class User extends Base
|
|||
|
||||
if ($code) {
|
||||
|
||||
$profile = $this->google->getGoogleProfile($code);
|
||||
$profile = $this->authentication->backend('google')->getGoogleProfile($code);
|
||||
|
||||
if (is_array($profile)) {
|
||||
|
||||
// If the user is already logged, link the account otherwise authenticate
|
||||
if ($this->acl->isLogged()) {
|
||||
|
||||
if ($this->google->updateUser($this->acl->getUserId(), $profile)) {
|
||||
if ($this->authentication->backend('google')->updateUser($this->acl->getUserId(), $profile)) {
|
||||
$this->session->flash(t('Your Google Account is linked to your profile successfully.'));
|
||||
}
|
||||
else {
|
||||
|
|
@ -265,7 +265,7 @@ class User extends Base
|
|||
|
||||
$this->response->redirect('?controller=user');
|
||||
}
|
||||
else if ($this->google->authenticate($profile['id'])) {
|
||||
else if ($this->authentication->backend('google')->authenticate($profile['id'])) {
|
||||
$this->response->redirect('?controller=app');
|
||||
}
|
||||
else {
|
||||
|
|
@ -279,7 +279,7 @@ class User extends Base
|
|||
}
|
||||
}
|
||||
|
||||
$this->response->redirect($this->google->getAuthorizationUrl());
|
||||
$this->response->redirect($this->authentication->backend('google')->getAuthorizationUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -290,7 +290,7 @@ class User extends Base
|
|||
public function unlinkGoogle()
|
||||
{
|
||||
$this->checkCSRFParam();
|
||||
if ($this->google->unlink($this->acl->getUserId())) {
|
||||
if ($this->authentication->backend('google')->unlink($this->acl->getUserId())) {
|
||||
$this->session->flash(t('Your Google Account is not linked anymore to your profile.'));
|
||||
}
|
||||
else {
|
||||
|
|
@ -310,14 +310,14 @@ class User extends Base
|
|||
$code = $this->request->getStringParam('code');
|
||||
|
||||
if ($code) {
|
||||
$profile = $this->gitHub->getGitHubProfile($code);
|
||||
$profile = $this->authentication->backend('gitHub')->getGitHubProfile($code);
|
||||
|
||||
if (is_array($profile)) {
|
||||
|
||||
// If the user is already logged, link the account otherwise authenticate
|
||||
if ($this->acl->isLogged()) {
|
||||
|
||||
if ($this->gitHub->updateUser($this->acl->getUserId(), $profile)) {
|
||||
if ($this->authentication->backend('gitHub')->updateUser($this->acl->getUserId(), $profile)) {
|
||||
$this->session->flash(t('Your GitHub account was successfully linked to your profile.'));
|
||||
}
|
||||
else {
|
||||
|
|
@ -326,7 +326,7 @@ class User extends Base
|
|||
|
||||
$this->response->redirect('?controller=user');
|
||||
}
|
||||
else if ($this->gitHub->authenticate($profile['id'])) {
|
||||
else if ($this->authentication->backend('gitHub')->authenticate($profile['id'])) {
|
||||
$this->response->redirect('?controller=app');
|
||||
}
|
||||
else {
|
||||
|
|
@ -340,7 +340,7 @@ class User extends Base
|
|||
}
|
||||
}
|
||||
|
||||
$this->response->redirect($this->gitHub->getAuthorizationUrl());
|
||||
$this->response->redirect($this->authentication->backend('gitHub')->getAuthorizationUrl());
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -352,9 +352,9 @@ class User extends Base
|
|||
{
|
||||
$this->checkCSRFParam();
|
||||
|
||||
$this->gitHub->revokeGitHubAccess();
|
||||
$this->authentication->backend('gitHub')->revokeGitHubAccess();
|
||||
|
||||
if ($this->gitHub->unlink($this->acl->getUserId())) {
|
||||
if ($this->authentication->backend('gitHub')->unlink($this->acl->getUserId())) {
|
||||
$this->session->flash(t('Your GitHub account is no longer linked to your profile.'));
|
||||
}
|
||||
else {
|
||||
|
|
|
|||
|
|
@ -34,8 +34,11 @@ class Tool
|
|||
|
||||
public static function loadModel(Registry $registry, $name)
|
||||
{
|
||||
$class = '\Model\\'.ucfirst($name);
|
||||
$registry->$name = new $class($registry);
|
||||
if (! isset($registry->$name)) {
|
||||
$class = '\Model\\'.ucfirst($name);
|
||||
$registry->$name = new $class($registry);
|
||||
}
|
||||
|
||||
return $registry->shared($name);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,125 @@
|
|||
<?php
|
||||
|
||||
namespace Model;
|
||||
|
||||
use Auth\Database;
|
||||
use SimpleValidator\Validator;
|
||||
use SimpleValidator\Validators;
|
||||
|
||||
/**
|
||||
* Authentication model
|
||||
*
|
||||
* @package model
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Authentication extends Base
|
||||
{
|
||||
/**
|
||||
* Load automatically an authentication backend
|
||||
*
|
||||
* @access public
|
||||
* @param string $name Backend class name
|
||||
* @return mixed
|
||||
*/
|
||||
public function backend($name)
|
||||
{
|
||||
if (! isset($this->registry->$name)) {
|
||||
$class = '\Auth\\'.ucfirst($name);
|
||||
$this->registry->$name = new $class($this->registry);
|
||||
}
|
||||
|
||||
return $this->registry->shared($name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the current user is authenticated
|
||||
*
|
||||
* @access public
|
||||
* @param string $controller Controller
|
||||
* @param string $action Action name
|
||||
* @return bool
|
||||
*/
|
||||
public function isAuthenticated($controller, $action)
|
||||
{
|
||||
// If the action is public we don't need to do any checks
|
||||
if ($this->acl->isPublicAction($controller, $action)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// If the user is already logged it's ok
|
||||
if ($this->acl->isLogged()) {
|
||||
|
||||
// We update each time the RememberMe cookie tokens
|
||||
if ($this->backend('rememberMe')->hasCookie()) {
|
||||
$this->backend('rememberMe')->refresh();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// We try first with the RememberMe cookie
|
||||
if ($this->backend('rememberMe')->authenticate()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Then with the ReverseProxy authentication
|
||||
if (REVERSE_PROXY_AUTH && $this->backend('reverseProxy')->authenticate()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate user login form
|
||||
*
|
||||
* @access public
|
||||
* @param array $values Form values
|
||||
* @return array $valid, $errors [0] = Success or not, [1] = List of errors
|
||||
*/
|
||||
public function validateForm(array $values)
|
||||
{
|
||||
$v = new Validator($values, array(
|
||||
new Validators\Required('username', t('The username is required')),
|
||||
new Validators\MaxLength('username', t('The maximum length is %d characters', 50), 50),
|
||||
new Validators\Required('password', t('The password is required')),
|
||||
));
|
||||
|
||||
$result = $v->execute();
|
||||
$errors = $v->getErrors();
|
||||
|
||||
if ($result) {
|
||||
|
||||
$authenticated = false;
|
||||
|
||||
// Try first the database auth and then LDAP if activated
|
||||
if ($this->backend('database')->authenticate($values['username'], $values['password'])) {
|
||||
$authenticated = true;
|
||||
}
|
||||
else if (LDAP_AUTH && $this->backend('ldap')->authenticate($values['username'], $values['password'])) {
|
||||
$authenticated = true;
|
||||
}
|
||||
|
||||
if ($authenticated) {
|
||||
|
||||
// Setup the remember me feature
|
||||
if (! empty($values['remember_me'])) {
|
||||
|
||||
$credentials = $this->backend('rememberMe')
|
||||
->create($this->acl->getUserId(), $this->user->getIpAddress(), $this->user->getUserAgent());
|
||||
|
||||
$this->backend('rememberMe')->writeCookie($credentials['token'], $credentials['sequence'], $credentials['expiration']);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$result = false;
|
||||
$errors['login'] = t('Bad username or password');
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
$result,
|
||||
$errors
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -2,20 +2,6 @@
|
|||
|
||||
namespace Model;
|
||||
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validator.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Base.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validators/Required.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validators/Unique.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validators/MaxLength.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validators/MinLength.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validators/Integer.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validators/Equals.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validators/AlphaNumeric.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validators/GreaterThan.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validators/Date.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validators/Email.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validators/Numeric.php';
|
||||
|
||||
use Core\Event;
|
||||
use Core\Tool;
|
||||
use Core\Registry;
|
||||
|
|
@ -35,7 +21,6 @@ use PicoDb\Database;
|
|||
* @property \Model\Config $config
|
||||
* @property \Model\File $file
|
||||
* @property \Model\LastLogin $lastLogin
|
||||
* @property \Model\Ldap $ldap
|
||||
* @property \Model\Notification $notification
|
||||
* @property \Model\Project $project
|
||||
* @property \Model\SubTask $subTask
|
||||
|
|
|
|||
|
|
@ -24,18 +24,6 @@ class LastLogin extends Base
|
|||
*/
|
||||
const NB_LOGINS = 10;
|
||||
|
||||
/**
|
||||
* Authentication methods
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const AUTH_DATABASE = 'database';
|
||||
const AUTH_REMEMBER_ME = 'remember_me';
|
||||
const AUTH_LDAP = 'ldap';
|
||||
const AUTH_GOOGLE = 'google';
|
||||
const AUTH_GITHUB = 'github';
|
||||
const AUTH_REVERSE_PROXY = 'reverse_proxy';
|
||||
|
||||
/**
|
||||
* Create a new record
|
||||
*
|
||||
|
|
|
|||
|
|
@ -1,104 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace Model;
|
||||
|
||||
/**
|
||||
* LDAP model
|
||||
*
|
||||
* @package model
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Ldap extends Base
|
||||
{
|
||||
/**
|
||||
* Authenticate a user
|
||||
*
|
||||
* @access public
|
||||
* @param string $username Username
|
||||
* @param string $password Password
|
||||
* @return null|boolean
|
||||
*/
|
||||
public function authenticate($username, $password)
|
||||
{
|
||||
if (! function_exists('ldap_connect')) {
|
||||
die('The PHP LDAP extension is required');
|
||||
}
|
||||
|
||||
// Skip SSL certificate verification
|
||||
if (! LDAP_SSL_VERIFY) {
|
||||
putenv('LDAPTLS_REQCERT=never');
|
||||
}
|
||||
|
||||
$ldap = ldap_connect(LDAP_SERVER, LDAP_PORT);
|
||||
|
||||
if (! is_resource($ldap)) {
|
||||
die('Unable to connect to the LDAP server: "'.LDAP_SERVER.'"');
|
||||
}
|
||||
|
||||
ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
|
||||
ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
|
||||
|
||||
if (! @ldap_bind($ldap, LDAP_USERNAME, LDAP_PASSWORD)) {
|
||||
die('Unable to bind to the LDAP server: "'.LDAP_SERVER.'"');
|
||||
}
|
||||
|
||||
$sr = @ldap_search($ldap, LDAP_ACCOUNT_BASE, sprintf(LDAP_USER_PATTERN, $username), array(LDAP_ACCOUNT_FULLNAME, LDAP_ACCOUNT_EMAIL));
|
||||
|
||||
if ($sr === false) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$info = ldap_get_entries($ldap, $sr);
|
||||
|
||||
// User not found
|
||||
if (count($info) == 0 || $info['count'] == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (@ldap_bind($ldap, $info[0]['dn'], $password)) {
|
||||
return $this->create($username, $info[0][LDAP_ACCOUNT_FULLNAME][0], $info[0][LDAP_ACCOUNT_EMAIL][0]);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create automatically a new local user after the LDAP authentication
|
||||
*
|
||||
* @access public
|
||||
* @param string $username Username
|
||||
* @param string $name Name of the user
|
||||
* @param string $email Email address
|
||||
* @return bool
|
||||
*/
|
||||
public function create($username, $name, $email)
|
||||
{
|
||||
$user = $this->user->getByUsername($username);
|
||||
|
||||
// There is an existing user account
|
||||
if ($user) {
|
||||
|
||||
if ($user['is_ldap_user'] == 1) {
|
||||
|
||||
// LDAP user already created
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
|
||||
// There is already a local user with that username
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Create a LDAP user
|
||||
$values = array(
|
||||
'username' => $username,
|
||||
'name' => $name,
|
||||
'email' => $email,
|
||||
'is_admin' => 0,
|
||||
'is_ldap_user' => 1,
|
||||
);
|
||||
|
||||
return $userModel->create($values);
|
||||
}
|
||||
}
|
||||
|
|
@ -311,84 +311,6 @@ class User extends Base
|
|||
return array(false, $v->getErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate user login
|
||||
*
|
||||
* @access public
|
||||
* @param array $values Form values
|
||||
* @return array $valid, $errors [0] = Success or not, [1] = List of errors
|
||||
*/
|
||||
public function validateLogin(array $values)
|
||||
{
|
||||
$v = new Validator($values, array(
|
||||
new Validators\Required('username', t('The username is required')),
|
||||
new Validators\MaxLength('username', t('The maximum length is %d characters', 50), 50),
|
||||
new Validators\Required('password', t('The password is required')),
|
||||
));
|
||||
|
||||
$result = $v->execute();
|
||||
$errors = $v->getErrors();
|
||||
|
||||
if ($result) {
|
||||
|
||||
list($authenticated, $method) = $this->authenticate($values['username'], $values['password']);
|
||||
|
||||
if ($authenticated === true) {
|
||||
|
||||
// Create the user session
|
||||
$user = $this->getByUsername($values['username']);
|
||||
$this->updateSession($user);
|
||||
|
||||
// Update login history
|
||||
$this->lastLogin->create(
|
||||
$method,
|
||||
$user['id'],
|
||||
$this->getIpAddress(),
|
||||
$this->getUserAgent()
|
||||
);
|
||||
|
||||
// Setup the remember me feature
|
||||
if (! empty($values['remember_me'])) {
|
||||
$credentials = $this->rememberMe->create($user['id'], $this->getIpAddress(), $this->getUserAgent());
|
||||
$this->rememberMe->writeCookie($credentials['token'], $credentials['sequence'], $credentials['expiration']);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$result = false;
|
||||
$errors['login'] = t('Bad username or password');
|
||||
}
|
||||
}
|
||||
|
||||
return array(
|
||||
$result,
|
||||
$errors
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate a user
|
||||
*
|
||||
* @access public
|
||||
* @param string $username Username
|
||||
* @param string $password Password
|
||||
* @return array
|
||||
*/
|
||||
public function authenticate($username, $password)
|
||||
{
|
||||
// Database authentication
|
||||
$user = $this->db->table(self::TABLE)->eq('username', $username)->eq('is_ldap_user', 0)->findOne();
|
||||
$authenticated = $user && \password_verify($password, $user['password']);
|
||||
$method = LastLogin::AUTH_DATABASE;
|
||||
|
||||
// LDAP authentication
|
||||
if (! $authenticated && LDAP_AUTH) {
|
||||
$authenticated = $this->ldap->authenticate($username, $password);
|
||||
$method = LastLogin::AUTH_LDAP;
|
||||
}
|
||||
|
||||
return array($authenticated, $method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the user agent of the connected user
|
||||
*
|
||||
|
|
|
|||
|
|
@ -4,7 +4,19 @@ require __DIR__.'/Core/Loader.php';
|
|||
require __DIR__.'/helpers.php';
|
||||
require __DIR__.'/translator.php';
|
||||
|
||||
require 'vendor/swiftmailer/swift_required.php';
|
||||
require __DIR__.'/../vendor/SimpleValidator/Validator.php';
|
||||
require __DIR__.'/../vendor/SimpleValidator/Base.php';
|
||||
require __DIR__.'/../vendor/SimpleValidator/Validators/Required.php';
|
||||
require __DIR__.'/../vendor/SimpleValidator/Validators/Unique.php';
|
||||
require __DIR__.'/../vendor/SimpleValidator/Validators/MaxLength.php';
|
||||
require __DIR__.'/../vendor/SimpleValidator/Validators/MinLength.php';
|
||||
require __DIR__.'/../vendor/SimpleValidator/Validators/Integer.php';
|
||||
require __DIR__.'/../vendor/SimpleValidator/Validators/Equals.php';
|
||||
require __DIR__.'/../vendor/SimpleValidator/Validators/AlphaNumeric.php';
|
||||
require __DIR__.'/../vendor/SimpleValidator/Validators/GreaterThan.php';
|
||||
require __DIR__.'/../vendor/SimpleValidator/Validators/Date.php';
|
||||
require __DIR__.'/../vendor/SimpleValidator/Validators/Email.php';
|
||||
require __DIR__.'/../vendor/SimpleValidator/Validators/Numeric.php';
|
||||
|
||||
use Core\Event;
|
||||
use Core\Loader;
|
||||
|
|
@ -47,6 +59,10 @@ defined('LDAP_AUTH') or define('LDAP_AUTH', false);
|
|||
defined('LDAP_SERVER') or define('LDAP_SERVER', '');
|
||||
defined('LDAP_PORT') or define('LDAP_PORT', 389);
|
||||
defined('LDAP_SSL_VERIFY') or define('LDAP_SSL_VERIFY', true);
|
||||
defined('LDAP_USERNAME') or define('LDAP_USERNAME', null);
|
||||
defined('LDAP_PASSWORD') or define('LDAP_PASSWORD', null);
|
||||
defined('LDAP_ACCOUNT_BASE') or define('LDAP_ACCOUNT_BASE', '');
|
||||
defined('LDAP_USER_PATTERN') or define('LDAP_USER_PATTERN', '');
|
||||
defined('LDAP_ACCOUNT_FULLNAME') or define('LDAP_ACCOUNT_FULLNAME', 'displayname');
|
||||
defined('LDAP_ACCOUNT_EMAIL') or define('LDAP_ACCOUNT_EMAIL', 'mail');
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ define('LDAP_USERNAME', null);
|
|||
define('LDAP_PASSWORD', null);
|
||||
|
||||
// LDAP account base, i.e. root of all user account
|
||||
// Example: ou=people,dc=example,dc=com
|
||||
// Example: ou=People,dc=example,dc=com
|
||||
define('LDAP_ACCOUNT_BASE', '');
|
||||
|
||||
// LDAP query pattern to use when searching for a user account
|
||||
|
|
|
|||
|
|
@ -23,17 +23,54 @@ Differences between a local user and a LDAP user are the following:
|
|||
- By default, all LDAP users have no admin privileges
|
||||
- To become administrator, a LDAP user must be promoted by another administrator
|
||||
|
||||
The full name and the email address are automatically fetched from the LDAP server.
|
||||
|
||||
Configuration
|
||||
-------------
|
||||
|
||||
The first step is to create a custom config file named `config.php`.
|
||||
This file must be stored in the root directory.
|
||||
You have to create a custom config file named `config.php` (you can also use the template `config.default.php`).
|
||||
This file must be stored in the root directory of Kanboard.
|
||||
|
||||
To do that, you can create an empty PHP file or copy/rename the sample file `config.default.php`.
|
||||
### Available configuration parameters
|
||||
|
||||
```php
|
||||
// Enable LDAP authentication (false by default)
|
||||
define('LDAP_AUTH', false);
|
||||
|
||||
// LDAP server hostname
|
||||
define('LDAP_SERVER', '');
|
||||
|
||||
// LDAP server port (389 by default)
|
||||
define('LDAP_PORT', 389);
|
||||
|
||||
// By default, require certificate to be verified for ldaps:// style URL. Set to false to skip the verification.
|
||||
define('LDAP_SSL_VERIFY', true);
|
||||
|
||||
// LDAP username to connect with. NULL for anonymous bind (by default).
|
||||
define('LDAP_USERNAME', null);
|
||||
|
||||
// LDAP password to connect with. NULL for anonymous bind (by default).
|
||||
define('LDAP_PASSWORD', null);
|
||||
|
||||
// LDAP account base, i.e. root of all user account
|
||||
// Example: ou=People,dc=example,dc=com
|
||||
define('LDAP_ACCOUNT_BASE', '');
|
||||
|
||||
// LDAP query pattern to use when searching for a user account
|
||||
// Example for ActiveDirectory: '(&(objectClass=user)(sAMAccountName=%s))'
|
||||
// Example for OpenLDAP: 'uid=%s'
|
||||
define('LDAP_USER_PATTERN', '');
|
||||
|
||||
// Name of an attribute of the user account object which should be used as the full name of the user.
|
||||
define('LDAP_ACCOUNT_FULLNAME', 'displayname');
|
||||
|
||||
// Name of an attribute of the user account object which should be used as the email of the user.
|
||||
define('LDAP_ACCOUNT_EMAIL', 'mail');
|
||||
```
|
||||
|
||||
### Example for Microsoft Active Directory
|
||||
|
||||
Let's say we have a domain `MYDOMAIN` (mydomain.local) and the primary controller is `myserver.mydomain.local`.
|
||||
Let's say we have a domain `KANBOARD` (kanboard.local) and the primary controller is `myserver.kanboard.local`.
|
||||
|
||||
```php
|
||||
<?php
|
||||
|
|
@ -41,15 +78,18 @@ Let's say we have a domain `MYDOMAIN` (mydomain.local) and the primary controlle
|
|||
// Enable LDAP authentication (false by default)
|
||||
define('LDAP_AUTH', true);
|
||||
|
||||
// Set credentials for be allow to browse the LDAP directory
|
||||
define('LDAP_USERNAME', 'administrator@kanboard.local');
|
||||
define('LDAP_PASSWORD', 'my super secret password');
|
||||
|
||||
// LDAP server hostname
|
||||
define('LDAP_SERVER', 'myserver.mydomain.local');
|
||||
|
||||
// User LDAP DN
|
||||
define('LDAP_USER_DN', 'MYDOMAIN\\%s');
|
||||
|
||||
// Another way to do the same thing
|
||||
define('LDAP_USER_DN', '%s@mydomain.local');
|
||||
define('LDAP_SERVER', 'myserver.kanboard.local');
|
||||
|
||||
// LDAP properties
|
||||
define('LDAP_ACCOUNT_BASE', 'CN=Users,DC=kanboard,DC=local');
|
||||
define('LDAP_USER_PATTERN', '(&(objectClass=user)(sAMAccountName=%s))');
|
||||
define('LDAP_ACCOUNT_FULLNAME', 'displayname');
|
||||
define('LDAP_ACCOUNT_EMAIL', 'mail');
|
||||
```
|
||||
|
||||
### Example for OpenLDAP
|
||||
|
|
@ -65,9 +105,11 @@ define('LDAP_AUTH', true);
|
|||
// LDAP server hostname
|
||||
define('LDAP_SERVER', 'myserver.example.com');
|
||||
|
||||
// User LDAP DN
|
||||
define('LDAP_USER_DN', 'uid=%s,ou=People,dc=example,dc=com');
|
||||
|
||||
// LDAP properties
|
||||
define('LDAP_ACCOUNT_BASE', 'ou=People,dc=example,dc=com');
|
||||
define('LDAP_USER_PATTERN', 'uid=%s');
|
||||
define('LDAP_ACCOUNT_FULLNAME', 'displayname');
|
||||
define('LDAP_ACCOUNT_EMAIL', 'mail');
|
||||
```
|
||||
|
||||
The `%s` is replaced by the username for the parameter `LDAP_USER_DN`, so you can define a custom Distinguished Name.
|
||||
The `%s` is replaced by the username for the parameter `LDAP_USER_PATTERN`, so you can define a custom Distinguished Name.
|
||||
|
|
|
|||
|
|
@ -4,6 +4,20 @@ if (version_compare(PHP_VERSION, '5.5.0', '<')) {
|
|||
require __DIR__.'/../../vendor/password.php';
|
||||
}
|
||||
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validator.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Base.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validators/Required.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validators/Unique.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validators/MaxLength.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validators/MinLength.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validators/Integer.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validators/Equals.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validators/AlphaNumeric.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validators/GreaterThan.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validators/Date.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validators/Email.php';
|
||||
require __DIR__.'/../../vendor/SimpleValidator/Validators/Numeric.php';
|
||||
|
||||
require_once __DIR__.'/../../app/Core/Security.php';
|
||||
|
||||
require_once __DIR__.'/../../vendor/PicoDb/Database.php';
|
||||
|
|
|
|||
Loading…
Reference in New Issue