Authentication backends refactoring
This commit is contained in:
60
app/Auth/Base.php
Normal file
60
app/Auth/Base.php
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
52
app/Auth/Database.php
Normal file
52
app/Auth/Database.php
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
178
app/Auth/GitHub.php
Normal file
178
app/Auth/GitHub.php
Normal file
@@ -0,0 +1,178 @@
|
||||
<?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;
|
||||
}
|
||||
}
|
||||
153
app/Auth/Google.php
Normal file
153
app/Auth/Google.php
Normal file
@@ -0,0 +1,153 @@
|
||||
<?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;
|
||||
|
||||
/**
|
||||
* Google backend
|
||||
*
|
||||
* @package auth
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class Google extends Base
|
||||
{
|
||||
/**
|
||||
* Backend name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const AUTH_NAME = 'Google';
|
||||
|
||||
/**
|
||||
* Authenticate a Google user
|
||||
*
|
||||
* @access public
|
||||
* @param string $google_id Google unique id
|
||||
* @return boolean
|
||||
*/
|
||||
public function authenticate($google_id)
|
||||
{
|
||||
$user = $this->user->getByGoogleId($google_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 Google 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,
|
||||
'google_id' => '',
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the user table based on the Google profile information
|
||||
*
|
||||
* @access public
|
||||
* @param integer $user_id User id
|
||||
* @param array $profile Google profile
|
||||
* @return boolean
|
||||
*/
|
||||
public function updateUser($user_id, array $profile)
|
||||
{
|
||||
return $this->user->update(array(
|
||||
'id' => $user_id,
|
||||
'google_id' => $profile['id'],
|
||||
'email' => $profile['email'],
|
||||
'name' => $profile['name'],
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the Google service instance
|
||||
*
|
||||
* @access public
|
||||
* @return \OAuth\OAuth2\Service\Google
|
||||
*/
|
||||
public function getService()
|
||||
{
|
||||
$uriFactory = new UriFactory();
|
||||
$currentUri = $uriFactory->createFromSuperGlobalArray($_SERVER);
|
||||
$currentUri->setQuery('controller=user&action=google');
|
||||
|
||||
$storage = new Session(false);
|
||||
|
||||
$credentials = new Credentials(
|
||||
GOOGLE_CLIENT_ID,
|
||||
GOOGLE_CLIENT_SECRET,
|
||||
$currentUri->getAbsoluteUri()
|
||||
);
|
||||
|
||||
$serviceFactory = new ServiceFactory();
|
||||
|
||||
return $serviceFactory->createService(
|
||||
'google',
|
||||
$credentials,
|
||||
$storage,
|
||||
array('userinfo_email', 'userinfo_profile')
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the authorization URL
|
||||
*
|
||||
* @access public
|
||||
* @return \OAuth\Common\Http\Uri\Uri
|
||||
*/
|
||||
public function getAuthorizationUrl()
|
||||
{
|
||||
return $this->getService()->getAuthorizationUri();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Google profile information from the API
|
||||
*
|
||||
* @access public
|
||||
* @param string $code Google authorization code
|
||||
* @return bool|array
|
||||
*/
|
||||
public function getGoogleProfile($code)
|
||||
{
|
||||
try {
|
||||
|
||||
$googleService = $this->getService();
|
||||
$googleService->requestAccessToken($code);
|
||||
return json_decode($googleService->request('https://www.googleapis.com/oauth2/v1/userinfo'), true);
|
||||
}
|
||||
catch (TokenResponseException $e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
150
app/Auth/Ldap.php
Normal file
150
app/Auth/Ldap.php
Normal file
@@ -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);
|
||||
}
|
||||
}
|
||||
349
app/Auth/RememberMe.php
Normal file
349
app/Auth/RememberMe.php
Normal file
@@ -0,0 +1,349 @@
|
||||
<?php
|
||||
|
||||
namespace Auth;
|
||||
|
||||
use Core\Security;
|
||||
|
||||
/**
|
||||
* RememberMe model
|
||||
*
|
||||
* @package auth
|
||||
* @author Frederic Guillot
|
||||
*/
|
||||
class RememberMe extends Base
|
||||
{
|
||||
/**
|
||||
* Backend name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const AUTH_NAME = 'RememberMe';
|
||||
|
||||
/**
|
||||
* SQL table name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const TABLE = 'remember_me';
|
||||
|
||||
/**
|
||||
* Cookie name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const COOKIE_NAME = '__R';
|
||||
|
||||
/**
|
||||
* Expiration (60 days)
|
||||
*
|
||||
* @var integer
|
||||
*/
|
||||
const EXPIRATION = 5184000;
|
||||
|
||||
/**
|
||||
* Get a remember me record
|
||||
*
|
||||
* @access public
|
||||
* @param $token
|
||||
* @param $sequence
|
||||
* @return mixed
|
||||
*/
|
||||
public function find($token, $sequence)
|
||||
{
|
||||
return $this->db
|
||||
->table(self::TABLE)
|
||||
->eq('token', $token)
|
||||
->eq('sequence', $sequence)
|
||||
->gt('expiration', time())
|
||||
->findOne();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all sessions for a given user
|
||||
*
|
||||
* @access public
|
||||
* @param integer $user_id User id
|
||||
* @return array
|
||||
*/
|
||||
public function getAll($user_id)
|
||||
{
|
||||
return $this->db
|
||||
->table(self::TABLE)
|
||||
->eq('user_id', $user_id)
|
||||
->desc('date_creation')
|
||||
->columns('id', 'ip', 'user_agent', 'date_creation', 'expiration')
|
||||
->findAll();
|
||||
}
|
||||
|
||||
/**
|
||||
* Authenticate the user with the cookie
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function authenticate()
|
||||
{
|
||||
$credentials = $this->readCookie();
|
||||
|
||||
if ($credentials !== false) {
|
||||
|
||||
$record = $this->find($credentials['token'], $credentials['sequence']);
|
||||
|
||||
if ($record) {
|
||||
|
||||
// Update the sequence
|
||||
$this->writeCookie(
|
||||
$record['token'],
|
||||
$this->update($record['token'], $record['sequence']),
|
||||
$record['expiration']
|
||||
);
|
||||
|
||||
// Create the session
|
||||
$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;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the database and the cookie with a new sequence
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function refresh()
|
||||
{
|
||||
$credentials = $this->readCookie();
|
||||
|
||||
if ($credentials !== false) {
|
||||
|
||||
$record = $this->find($credentials['token'], $credentials['sequence']);
|
||||
|
||||
if ($record) {
|
||||
|
||||
// Update the sequence
|
||||
$this->writeCookie(
|
||||
$record['token'],
|
||||
$this->update($record['token'], $record['sequence']),
|
||||
$record['expiration']
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a session record
|
||||
*
|
||||
* @access public
|
||||
* @param integer $session_id Session id
|
||||
* @return mixed
|
||||
*/
|
||||
public function remove($session_id)
|
||||
{
|
||||
return $this->db
|
||||
->table(self::TABLE)
|
||||
->eq('id', $session_id)
|
||||
->remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the current RememberMe session and the cookie
|
||||
*
|
||||
* @access public
|
||||
* @param integer $user_id User id
|
||||
*/
|
||||
public function destroy($user_id)
|
||||
{
|
||||
$credentials = $this->readCookie();
|
||||
|
||||
if ($credentials !== false) {
|
||||
|
||||
$this->deleteCookie();
|
||||
|
||||
$this->db
|
||||
->table(self::TABLE)
|
||||
->eq('user_id', $user_id)
|
||||
->eq('token', $credentials['token'])
|
||||
->remove();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new RememberMe session
|
||||
*
|
||||
* @access public
|
||||
* @param integer $user_id User id
|
||||
* @param string $ip IP Address
|
||||
* @param string $user_agent User Agent
|
||||
* @return array
|
||||
*/
|
||||
public function create($user_id, $ip, $user_agent)
|
||||
{
|
||||
$token = hash('sha256', $user_id.$user_agent.$ip.Security::generateToken());
|
||||
$sequence = Security::generateToken();
|
||||
$expiration = time() + self::EXPIRATION;
|
||||
|
||||
$this->cleanup($user_id);
|
||||
|
||||
$this->db
|
||||
->table(self::TABLE)
|
||||
->insert(array(
|
||||
'user_id' => $user_id,
|
||||
'ip' => $ip,
|
||||
'user_agent' => $user_agent,
|
||||
'token' => $token,
|
||||
'sequence' => $sequence,
|
||||
'expiration' => $expiration,
|
||||
'date_creation' => time(),
|
||||
));
|
||||
|
||||
return array(
|
||||
'token' => $token,
|
||||
'sequence' => $sequence,
|
||||
'expiration' => $expiration,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove old sessions for a given user
|
||||
*
|
||||
* @access public
|
||||
* @param integer $user_id User id
|
||||
* @return bool
|
||||
*/
|
||||
public function cleanup($user_id)
|
||||
{
|
||||
return $this->db
|
||||
->table(self::TABLE)
|
||||
->eq('user_id', $user_id)
|
||||
->lt('expiration', time())
|
||||
->remove();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a new sequence token and update the database
|
||||
*
|
||||
* @access public
|
||||
* @param string $token Session token
|
||||
* @param string $sequence Sequence token
|
||||
* @return string
|
||||
*/
|
||||
public function update($token, $sequence)
|
||||
{
|
||||
$new_sequence = Security::generateToken();
|
||||
|
||||
$this->db
|
||||
->table(self::TABLE)
|
||||
->eq('token', $token)
|
||||
->eq('sequence', $sequence)
|
||||
->update(array('sequence' => $new_sequence));
|
||||
|
||||
return $new_sequence;
|
||||
}
|
||||
|
||||
/**
|
||||
* Encode the cookie
|
||||
*
|
||||
* @access public
|
||||
* @param string $token Session token
|
||||
* @param string $sequence Sequence token
|
||||
* @return string
|
||||
*/
|
||||
public function encodeCookie($token, $sequence)
|
||||
{
|
||||
return implode('|', array($token, $sequence));
|
||||
}
|
||||
|
||||
/**
|
||||
* Decode the value of a cookie
|
||||
*
|
||||
* @access public
|
||||
* @param string $value Raw cookie data
|
||||
* @return array
|
||||
*/
|
||||
public function decodeCookie($value)
|
||||
{
|
||||
list($token, $sequence) = explode('|', $value);
|
||||
|
||||
return array(
|
||||
'token' => $token,
|
||||
'sequence' => $sequence,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if the current user has a RememberMe cookie
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function hasCookie()
|
||||
{
|
||||
return ! empty($_COOKIE[self::COOKIE_NAME]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write and encode the cookie
|
||||
*
|
||||
* @access public
|
||||
* @param string $token Session token
|
||||
* @param string $sequence Sequence token
|
||||
* @param string $expiration Cookie expiration
|
||||
*/
|
||||
public function writeCookie($token, $sequence, $expiration)
|
||||
{
|
||||
setcookie(
|
||||
self::COOKIE_NAME,
|
||||
$this->encodeCookie($token, $sequence),
|
||||
$expiration,
|
||||
BASE_URL_DIRECTORY,
|
||||
null,
|
||||
! empty($_SERVER['HTTPS']),
|
||||
true
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Read and decode the cookie
|
||||
*
|
||||
* @access public
|
||||
* @return mixed
|
||||
*/
|
||||
public function readCookie()
|
||||
{
|
||||
if (empty($_COOKIE[self::COOKIE_NAME])) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return $this->decodeCookie($_COOKIE[self::COOKIE_NAME]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the cookie
|
||||
*
|
||||
* @access public
|
||||
*/
|
||||
public function deleteCookie()
|
||||
{
|
||||
setcookie(
|
||||
self::COOKIE_NAME,
|
||||
'',
|
||||
time() - 3600,
|
||||
BASE_URL_DIRECTORY,
|
||||
null,
|
||||
! empty($_SERVER['HTTPS']),
|
||||
true
|
||||
);
|
||||
}
|
||||
}
|
||||
73
app/Auth/ReverseProxy.php
Normal file
73
app/Auth/ReverseProxy.php
Normal file
@@ -0,0 +1,73 @@
|
||||
<?php
|
||||
|
||||
namespace Auth;
|
||||
|
||||
use Core\Security;
|
||||
|
||||
/**
|
||||
* ReverseProxy backend
|
||||
*
|
||||
* @package auth
|
||||
* @author Sylvain Veyrié
|
||||
*/
|
||||
class ReverseProxy extends Base
|
||||
{
|
||||
/**
|
||||
* Backend name
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
const AUTH_NAME = 'ReverseProxy';
|
||||
|
||||
/**
|
||||
* Authenticate the user with the HTTP header
|
||||
*
|
||||
* @access public
|
||||
* @return bool
|
||||
*/
|
||||
public function authenticate()
|
||||
{
|
||||
if (isset($_SERVER[REVERSE_PROXY_USER_HEADER])) {
|
||||
|
||||
$login = $_SERVER[REVERSE_PROXY_USER_HEADER];
|
||||
$user = $this->user->getByUsername($login);
|
||||
|
||||
if (! $user) {
|
||||
$this->createUser($login);
|
||||
$user = $this->user->getByUsername($login);
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create automatically a new local user after the authentication
|
||||
*
|
||||
* @access private
|
||||
* @param string $login Username
|
||||
* @return bool
|
||||
*/
|
||||
private function createUser($login)
|
||||
{
|
||||
return $this->user->create(array(
|
||||
'email' => strpos($login, '@') !== false ? $login : '',
|
||||
'username' => $login,
|
||||
'is_admin' => REVERSE_PROXY_DEFAULT_ADMIN === $login,
|
||||
'is_ldap_user' => 1,
|
||||
));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user