summaryrefslogtreecommitdiff
path: root/app/Auth
diff options
context:
space:
mode:
authorFrederic Guillot <fred@kanboard.net>2015-12-05 20:31:27 -0500
committerFrederic Guillot <fred@kanboard.net>2015-12-05 20:31:27 -0500
commite9fedf3e5cd63aea4da7a71f6647ee427c62fa49 (patch)
treeabc2de5aebace4a2d7c94805552264dab6b10bc7 /app/Auth
parent346b8312e5ac877ce3192c2db3a26b500018bbb5 (diff)
Rewrite of the authentication and authorization system
Diffstat (limited to 'app/Auth')
-rw-r--r--app/Auth/DatabaseAuth.php125
-rw-r--r--app/Auth/Github.php123
-rw-r--r--app/Auth/GithubAuth.php143
-rw-r--r--app/Auth/Gitlab.php123
-rw-r--r--app/Auth/GitlabAuth.php143
-rw-r--r--app/Auth/Google.php124
-rw-r--r--app/Auth/GoogleAuth.php143
-rw-r--r--app/Auth/Ldap.php521
-rw-r--r--app/Auth/LdapAuth.php187
-rw-r--r--app/Auth/RememberMe.php323
-rw-r--r--app/Auth/RememberMeAuth.php79
-rw-r--r--app/Auth/ReverseProxy.php83
-rw-r--r--app/Auth/ReverseProxyAuth.php76
-rw-r--r--app/Auth/TotpAuth.php126
14 files changed, 1022 insertions, 1297 deletions
diff --git a/app/Auth/DatabaseAuth.php b/app/Auth/DatabaseAuth.php
new file mode 100644
index 00000000..727afaf3
--- /dev/null
+++ b/app/Auth/DatabaseAuth.php
@@ -0,0 +1,125 @@
+<?php
+
+namespace Kanboard\Auth;
+
+use Kanboard\Core\Base;
+use Kanboard\Core\Security\PasswordAuthenticationProviderInterface;
+use Kanboard\Core\Security\SessionCheckProviderInterface;
+use Kanboard\Model\User;
+use Kanboard\User\DatabaseUserProvider;
+
+/**
+ * Database Authentication Provider
+ *
+ * @package auth
+ * @author Frederic Guillot
+ */
+class DatabaseAuth extends Base implements PasswordAuthenticationProviderInterface, SessionCheckProviderInterface
+{
+ /**
+ * User properties
+ *
+ * @access private
+ * @var array
+ */
+ private $userInfo = array();
+
+ /**
+ * Username
+ *
+ * @access private
+ * @var string
+ */
+ private $username = '';
+
+ /**
+ * Password
+ *
+ * @access private
+ * @var string
+ */
+ private $password = '';
+
+ /**
+ * Get authentication provider name
+ *
+ * @access public
+ * @return string
+ */
+ public function getName()
+ {
+ return 'Database';
+ }
+
+ /**
+ * Authenticate the user
+ *
+ * @access public
+ * @return boolean
+ */
+ public function authenticate()
+ {
+ $user = $this->db
+ ->table(User::TABLE)
+ ->columns('id', 'password')
+ ->eq('username', $this->username)
+ ->eq('disable_login_form', 0)
+ ->eq('is_ldap_user', 0)
+ ->findOne();
+
+ if (! empty($user) && password_verify($this->password, $user['password'])) {
+ $this->userInfo = $user;
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Check if the user session is valid
+ *
+ * @access public
+ * @return boolean
+ */
+ public function isValidSession()
+ {
+ return $this->user->exists($this->userSession->getId());
+ }
+
+ /**
+ * Get user object
+ *
+ * @access public
+ * @return null|\Kanboard\User\DatabaseUserProvider
+ */
+ public function getUser()
+ {
+ if (empty($this->userInfo)) {
+ return null;
+ }
+
+ return new DatabaseUserProvider($this->userInfo);
+ }
+
+ /**
+ * Set username
+ *
+ * @access public
+ * @param string $username
+ */
+ public function setUsername($username)
+ {
+ $this->username = $username;
+ }
+
+ /**
+ * Set password
+ *
+ * @access public
+ * @param string $password
+ */
+ public function setPassword($password)
+ {
+ $this->password = $password;
+ }
+}
diff --git a/app/Auth/Github.php b/app/Auth/Github.php
deleted file mode 100644
index 4777152a..00000000
--- a/app/Auth/Github.php
+++ /dev/null
@@ -1,123 +0,0 @@
-<?php
-
-namespace Kanboard\Auth;
-
-use Kanboard\Core\Base;
-use Kanboard\Event\AuthEvent;
-
-/**
- * Github backend
- *
- * @package auth
- */
-class Github extends Base
-{
- /**
- * Backend name
- *
- * @var string
- */
- const AUTH_NAME = 'Github';
-
- /**
- * OAuth2 instance
- *
- * @access private
- * @var \Kanboard\Core\OAuth2
- */
- private $service;
-
- /**
- * 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 (! empty($user)) {
- $this->userSession->initialize($user);
- $this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id']));
- 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
- */
- public function updateUser($user_id, array $profile)
- {
- $user = $this->user->getById($user_id);
-
- return $this->user->update(array(
- 'id' => $user_id,
- 'github_id' => $profile['id'],
- 'email' => empty($user['email']) ? $profile['email'] : $user['email'],
- 'name' => empty($user['name']) ? $profile['name'] : $user['name'],
- ));
- }
-
- /**
- * Get OAuth2 configured service
- *
- * @access public
- * @return Kanboard\Core\OAuth2
- */
- public function getService()
- {
- if (empty($this->service)) {
- $this->service = $this->oauth->createService(
- GITHUB_CLIENT_ID,
- GITHUB_CLIENT_SECRET,
- $this->helper->url->to('oauth', 'github', array(), '', true),
- GITHUB_OAUTH_AUTHORIZE_URL,
- GITHUB_OAUTH_TOKEN_URL,
- array()
- );
- }
-
- return $this->service;
- }
-
- /**
- * Get Github profile
- *
- * @access public
- * @param string $code
- * @return array
- */
- public function getProfile($code)
- {
- $this->getService()->getAccessToken($code);
-
- return $this->httpClient->getJson(
- GITHUB_API_URL.'user',
- array($this->getService()->getAuthorizationHeader())
- );
- }
-}
diff --git a/app/Auth/GithubAuth.php b/app/Auth/GithubAuth.php
new file mode 100644
index 00000000..47da0413
--- /dev/null
+++ b/app/Auth/GithubAuth.php
@@ -0,0 +1,143 @@
+<?php
+
+namespace Kanboard\Auth;
+
+use Kanboard\Core\Base;
+use Kanboard\Core\Security\OAuthAuthenticationProviderInterface;
+use Kanboard\User\GithubUserProvider;
+
+/**
+ * Github Authentication Provider
+ *
+ * @package auth
+ * @author Frederic Guillot
+ */
+class GithubAuth extends Base implements OAuthAuthenticationProviderInterface
+{
+ /**
+ * User properties
+ *
+ * @access private
+ * @var \Kanboard\User\GithubUserProvider
+ */
+ private $userInfo = null;
+
+ /**
+ * OAuth2 instance
+ *
+ * @access private
+ * @var \Kanboard\Core\Http\OAuth2
+ */
+ private $service;
+
+ /**
+ * OAuth2 code
+ *
+ * @access private
+ * @var string
+ */
+ private $code = '';
+
+ /**
+ * Get authentication provider name
+ *
+ * @access public
+ * @return string
+ */
+ public function getName()
+ {
+ return 'Github';
+ }
+
+ /**
+ * Authenticate the user
+ *
+ * @access public
+ * @return boolean
+ */
+ public function authenticate()
+ {
+ $profile = $this->getProfile();
+
+ if (! empty($profile)) {
+ $this->userInfo = new GithubUserProvider($profile);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Set Code
+ *
+ * @access public
+ * @param string $code
+ * @return GithubAuth
+ */
+ public function setCode($code)
+ {
+ $this->code = $code;
+ return $this;
+ }
+
+ /**
+ * Get user object
+ *
+ * @access public
+ * @return null|GithubUserProvider
+ */
+ public function getUser()
+ {
+ return $this->userInfo;
+ }
+
+ /**
+ * Get configured OAuth2 service
+ *
+ * @access public
+ * @return \Kanboard\Core\Http\OAuth2
+ */
+ public function getService()
+ {
+ if (empty($this->service)) {
+ $this->service = $this->oauth->createService(
+ GITHUB_CLIENT_ID,
+ GITHUB_CLIENT_SECRET,
+ $this->helper->url->to('oauth', 'github', array(), '', true),
+ GITHUB_OAUTH_AUTHORIZE_URL,
+ GITHUB_OAUTH_TOKEN_URL,
+ array()
+ );
+ }
+
+ return $this->service;
+ }
+
+ /**
+ * Get Github profile
+ *
+ * @access private
+ * @return array
+ */
+ private function getProfile()
+ {
+ $this->getService()->getAccessToken($this->code);
+
+ return $this->httpClient->getJson(
+ GITHUB_API_URL.'user',
+ array($this->getService()->getAuthorizationHeader())
+ );
+ }
+
+ /**
+ * Unlink user
+ *
+ * @access public
+ * @param integer $userId
+ * @return bool
+ */
+ public function unlink($userId)
+ {
+ return $this->user->update(array('id' => $userId, 'github_id' => ''));
+ }
+}
diff --git a/app/Auth/Gitlab.php b/app/Auth/Gitlab.php
deleted file mode 100644
index 698b59c3..00000000
--- a/app/Auth/Gitlab.php
+++ /dev/null
@@ -1,123 +0,0 @@
-<?php
-
-namespace Kanboard\Auth;
-
-use Kanboard\Core\Base;
-use Kanboard\Event\AuthEvent;
-
-/**
- * Gitlab backend
- *
- * @package auth
- */
-class Gitlab extends Base
-{
- /**
- * Backend name
- *
- * @var string
- */
- const AUTH_NAME = 'Gitlab';
-
- /**
- * OAuth2 instance
- *
- * @access private
- * @var \Kanboard\Core\OAuth2
- */
- private $service;
-
- /**
- * Authenticate a Gitlab user
- *
- * @access public
- * @param string $gitlab_id Gitlab user id
- * @return boolean
- */
- public function authenticate($gitlab_id)
- {
- $user = $this->user->getByGitlabId($gitlab_id);
-
- if (! empty($user)) {
- $this->userSession->initialize($user);
- $this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id']));
- return true;
- }
-
- return false;
- }
-
- /**
- * Unlink a Gitlab 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,
- 'gitlab_id' => '',
- ));
- }
-
- /**
- * Update the user table based on the Gitlab profile information
- *
- * @access public
- * @param integer $user_id User id
- * @param array $profile Gitlab profile
- * @return boolean
- */
- public function updateUser($user_id, array $profile)
- {
- $user = $this->user->getById($user_id);
-
- return $this->user->update(array(
- 'id' => $user_id,
- 'gitlab_id' => $profile['id'],
- 'email' => empty($user['email']) ? $profile['email'] : $user['email'],
- 'name' => empty($user['name']) ? $profile['name'] : $user['name'],
- ));
- }
-
- /**
- * Get OAuth2 configured service
- *
- * @access public
- * @return Kanboard\Core\OAuth2
- */
- public function getService()
- {
- if (empty($this->service)) {
- $this->service = $this->oauth->createService(
- GITLAB_CLIENT_ID,
- GITLAB_CLIENT_SECRET,
- $this->helper->url->to('oauth', 'gitlab', array(), '', true),
- GITLAB_OAUTH_AUTHORIZE_URL,
- GITLAB_OAUTH_TOKEN_URL,
- array()
- );
- }
-
- return $this->service;
- }
-
- /**
- * Get Gitlab profile
- *
- * @access public
- * @param string $code
- * @return array
- */
- public function getProfile($code)
- {
- $this->getService()->getAccessToken($code);
-
- return $this->httpClient->getJson(
- GITLAB_API_URL.'user',
- array($this->getService()->getAuthorizationHeader())
- );
- }
-}
diff --git a/app/Auth/GitlabAuth.php b/app/Auth/GitlabAuth.php
new file mode 100644
index 00000000..df6e0176
--- /dev/null
+++ b/app/Auth/GitlabAuth.php
@@ -0,0 +1,143 @@
+<?php
+
+namespace Kanboard\Auth;
+
+use Kanboard\Core\Base;
+use Kanboard\Core\Security\OAuthAuthenticationProviderInterface;
+use Kanboard\User\GitlabUserProvider;
+
+/**
+ * Gitlab Authentication Provider
+ *
+ * @package auth
+ * @author Frederic Guillot
+ */
+class GitlabAuth extends Base implements OAuthAuthenticationProviderInterface
+{
+ /**
+ * User properties
+ *
+ * @access private
+ * @var \Kanboard\User\GitlabUserProvider
+ */
+ private $userInfo = null;
+
+ /**
+ * OAuth2 instance
+ *
+ * @access private
+ * @var \Kanboard\Core\Http\OAuth2
+ */
+ private $service;
+
+ /**
+ * OAuth2 code
+ *
+ * @access private
+ * @var string
+ */
+ private $code = '';
+
+ /**
+ * Get authentication provider name
+ *
+ * @access public
+ * @return string
+ */
+ public function getName()
+ {
+ return 'Gitlab';
+ }
+
+ /**
+ * Authenticate the user
+ *
+ * @access public
+ * @return boolean
+ */
+ public function authenticate()
+ {
+ $profile = $this->getProfile();
+
+ if (! empty($profile)) {
+ $this->userInfo = new GitlabUserProvider($profile);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Set Code
+ *
+ * @access public
+ * @param string $code
+ * @return GitlabAuth
+ */
+ public function setCode($code)
+ {
+ $this->code = $code;
+ return $this;
+ }
+
+ /**
+ * Get user object
+ *
+ * @access public
+ * @return null|GitlabUserProvider
+ */
+ public function getUser()
+ {
+ return $this->userInfo;
+ }
+
+ /**
+ * Get configured OAuth2 service
+ *
+ * @access public
+ * @return \Kanboard\Core\Http\OAuth2
+ */
+ public function getService()
+ {
+ if (empty($this->service)) {
+ $this->service = $this->oauth->createService(
+ GITLAB_CLIENT_ID,
+ GITLAB_CLIENT_SECRET,
+ $this->helper->url->to('oauth', 'gitlab', array(), '', true),
+ GITLAB_OAUTH_AUTHORIZE_URL,
+ GITLAB_OAUTH_TOKEN_URL,
+ array()
+ );
+ }
+
+ return $this->service;
+ }
+
+ /**
+ * Get Gitlab profile
+ *
+ * @access private
+ * @return array
+ */
+ private function getProfile()
+ {
+ $this->getService()->getAccessToken($this->code);
+
+ return $this->httpClient->getJson(
+ GITLAB_API_URL.'user',
+ array($this->getService()->getAuthorizationHeader())
+ );
+ }
+
+ /**
+ * Unlink user
+ *
+ * @access public
+ * @param integer $userId
+ * @return bool
+ */
+ public function unlink($userId)
+ {
+ return $this->user->update(array('id' => $userId, 'gitlab_id' => ''));
+ }
+}
diff --git a/app/Auth/Google.php b/app/Auth/Google.php
deleted file mode 100644
index 6c1bc3cd..00000000
--- a/app/Auth/Google.php
+++ /dev/null
@@ -1,124 +0,0 @@
-<?php
-
-namespace Kanboard\Auth;
-
-use Kanboard\Core\Base;
-use Kanboard\Event\AuthEvent;
-
-/**
- * Google backend
- *
- * @package auth
- * @author Frederic Guillot
- */
-class Google extends Base
-{
- /**
- * Backend name
- *
- * @var string
- */
- const AUTH_NAME = 'Google';
-
- /**
- * OAuth2 instance
- *
- * @access private
- * @var \Kanboard\Core\OAuth2
- */
- private $service;
-
- /**
- * 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 (! empty($user)) {
- $this->userSession->initialize($user);
- $this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id']));
- 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)
- {
- $user = $this->user->getById($user_id);
-
- return $this->user->update(array(
- 'id' => $user_id,
- 'google_id' => $profile['id'],
- 'email' => empty($user['email']) ? $profile['email'] : $user['email'],
- 'name' => empty($user['name']) ? $profile['name'] : $user['name'],
- ));
- }
-
- /**
- * Get OAuth2 configured service
- *
- * @access public
- * @return KanboardCore\OAuth2
- */
- public function getService()
- {
- if (empty($this->service)) {
- $this->service = $this->oauth->createService(
- GOOGLE_CLIENT_ID,
- GOOGLE_CLIENT_SECRET,
- $this->helper->url->to('oauth', 'google', array(), '', true),
- 'https://accounts.google.com/o/oauth2/auth',
- 'https://accounts.google.com/o/oauth2/token',
- array('https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile')
- );
- }
-
- return $this->service;
- }
-
- /**
- * Get Google profile
- *
- * @access public
- * @param string $code
- * @return array
- */
- public function getProfile($code)
- {
- $this->getService()->getAccessToken($code);
-
- return $this->httpClient->getJson(
- 'https://www.googleapis.com/oauth2/v1/userinfo',
- array($this->getService()->getAuthorizationHeader())
- );
- }
-}
diff --git a/app/Auth/GoogleAuth.php b/app/Auth/GoogleAuth.php
new file mode 100644
index 00000000..0dc1c62f
--- /dev/null
+++ b/app/Auth/GoogleAuth.php
@@ -0,0 +1,143 @@
+<?php
+
+namespace Kanboard\Auth;
+
+use Kanboard\Core\Base;
+use Kanboard\Core\Security\OAuthAuthenticationProviderInterface;
+use Kanboard\User\GoogleUserProvider;
+
+/**
+ * Google Authentication Provider
+ *
+ * @package auth
+ * @author Frederic Guillot
+ */
+class GoogleAuth extends Base implements OAuthAuthenticationProviderInterface
+{
+ /**
+ * User properties
+ *
+ * @access private
+ * @var \Kanboard\User\GoogleUserProvider
+ */
+ private $userInfo = null;
+
+ /**
+ * OAuth2 instance
+ *
+ * @access private
+ * @var \Kanboard\Core\Http\OAuth2
+ */
+ private $service;
+
+ /**
+ * OAuth2 code
+ *
+ * @access private
+ * @var string
+ */
+ private $code = '';
+
+ /**
+ * Get authentication provider name
+ *
+ * @access public
+ * @return string
+ */
+ public function getName()
+ {
+ return 'Google';
+ }
+
+ /**
+ * Authenticate the user
+ *
+ * @access public
+ * @return boolean
+ */
+ public function authenticate()
+ {
+ $profile = $this->getProfile();
+
+ if (! empty($profile)) {
+ $this->userInfo = new GoogleUserProvider($profile);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Set Code
+ *
+ * @access public
+ * @param string $code
+ * @return GoogleAuth
+ */
+ public function setCode($code)
+ {
+ $this->code = $code;
+ return $this;
+ }
+
+ /**
+ * Get user object
+ *
+ * @access public
+ * @return null|GoogleUserProvider
+ */
+ public function getUser()
+ {
+ return $this->userInfo;
+ }
+
+ /**
+ * Get configured OAuth2 service
+ *
+ * @access public
+ * @return \Kanboard\Core\Http\OAuth2
+ */
+ public function getService()
+ {
+ if (empty($this->service)) {
+ $this->service = $this->oauth->createService(
+ GOOGLE_CLIENT_ID,
+ GOOGLE_CLIENT_SECRET,
+ $this->helper->url->to('oauth', 'google', array(), '', true),
+ 'https://accounts.google.com/o/oauth2/auth',
+ 'https://accounts.google.com/o/oauth2/token',
+ array('https://www.googleapis.com/auth/userinfo.email', 'https://www.googleapis.com/auth/userinfo.profile')
+ );
+ }
+
+ return $this->service;
+ }
+
+ /**
+ * Get Google profile
+ *
+ * @access private
+ * @return array
+ */
+ private function getProfile()
+ {
+ $this->getService()->getAccessToken($this->code);
+
+ return $this->httpClient->getJson(
+ 'https://www.googleapis.com/oauth2/v1/userinfo',
+ array($this->getService()->getAuthorizationHeader())
+ );
+ }
+
+ /**
+ * Unlink user
+ *
+ * @access public
+ * @param integer $userId
+ * @return bool
+ */
+ public function unlink($userId)
+ {
+ return $this->user->update(array('id' => $userId, 'google_id' => ''));
+ }
+}
diff --git a/app/Auth/Ldap.php b/app/Auth/Ldap.php
deleted file mode 100644
index 3d361aa7..00000000
--- a/app/Auth/Ldap.php
+++ /dev/null
@@ -1,521 +0,0 @@
-<?php
-
-namespace Kanboard\Auth;
-
-use Kanboard\Core\Base;
-use Kanboard\Event\AuthEvent;
-
-/**
- * LDAP model
- *
- * @package auth
- * @author Frederic Guillot
- */
-class Ldap extends Base
-{
- /**
- * Backend name
- *
- * @var string
- */
- const AUTH_NAME = 'LDAP';
-
- /**
- * Get LDAP server name
- *
- * @access public
- * @return string
- */
- public function getLdapServer()
- {
- return LDAP_SERVER;
- }
-
- /**
- * Get LDAP bind type
- *
- * @access public
- * @return integer
- */
- public function getLdapBindType()
- {
- return LDAP_BIND_TYPE;
- }
-
- /**
- * Get LDAP server port
- *
- * @access public
- * @return integer
- */
- public function getLdapPort()
- {
- return LDAP_PORT;
- }
-
- /**
- * Get LDAP username (proxy auth)
- *
- * @access public
- * @return string
- */
- public function getLdapUsername()
- {
- return LDAP_USERNAME;
- }
-
- /**
- * Get LDAP password (proxy auth)
- *
- * @access public
- * @return string
- */
- public function getLdapPassword()
- {
- return LDAP_PASSWORD;
- }
-
- /**
- * Get LDAP Base DN
- *
- * @access public
- * @return string
- */
- public function getLdapBaseDn()
- {
- return LDAP_ACCOUNT_BASE;
- }
-
- /**
- * Get LDAP account id attribute
- *
- * @access public
- * @return string
- */
- public function getLdapAccountId()
- {
- return LDAP_ACCOUNT_ID;
- }
-
- /**
- * Get LDAP account email attribute
- *
- * @access public
- * @return string
- */
- public function getLdapAccountEmail()
- {
- return LDAP_ACCOUNT_EMAIL;
- }
-
- /**
- * Get LDAP account name attribute
- *
- * @access public
- * @return string
- */
- public function getLdapAccountName()
- {
- return LDAP_ACCOUNT_FULLNAME;
- }
-
- /**
- * Get LDAP account memberof attribute
- *
- * @access public
- * @return string
- */
- public function getLdapAccountMemberOf()
- {
- return LDAP_ACCOUNT_MEMBEROF;
- }
-
- /**
- * Get LDAP admin group DN
- *
- * @access public
- * @return string
- */
- public function getLdapGroupAdmin()
- {
- return LDAP_GROUP_ADMIN_DN;
- }
-
- /**
- * Get LDAP project admin group DN
- *
- * @access public
- * @return string
- */
- public function getLdapGroupProjectAdmin()
- {
- return LDAP_GROUP_PROJECT_ADMIN_DN;
- }
-
- /**
- * Get LDAP username pattern
- *
- * @access public
- * @param string $username
- * @return string
- */
- public function getLdapUserPattern($username)
- {
- return sprintf(LDAP_USER_PATTERN, $username);
- }
-
- /**
- * Return true if the LDAP username is case sensitive
- *
- * @access public
- * @return boolean
- */
- public function isLdapAccountCaseSensitive()
- {
- return LDAP_USERNAME_CASE_SENSITIVE;
- }
-
- /**
- * Return true if the automatic account creation is enabled
- *
- * @access public
- * @return boolean
- */
- public function isLdapAccountCreationEnabled()
- {
- return LDAP_ACCOUNT_CREATION;
- }
-
- /**
- * Ge the list of attributes to fetch when reading the LDAP user entry
- *
- * Must returns array with index that start at 0 otherwise ldap_search returns a warning "Array initialization wrong"
- *
- * @access public
- * @return array
- */
- public function getProfileAttributes()
- {
- return array_values(array_filter(array(
- $this->getLdapAccountId(),
- $this->getLdapAccountName(),
- $this->getLdapAccountEmail(),
- $this->getLdapAccountMemberOf()
- )));
- }
-
- /**
- * Authenticate the user
- *
- * @access public
- * @param string $username Username
- * @param string $password Password
- * @return boolean
- */
- public function authenticate($username, $password)
- {
- $username = $this->isLdapAccountCaseSensitive() ? $username : strtolower($username);
- $result = $this->findUser($username, $password);
-
- if (is_array($result)) {
- $user = $this->user->getByUsername($username);
-
- if (! empty($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->isLdapAccountCreationEnabled() && $this->user->create($result) !== false) {
- $user = $this->user->getByUsername($username);
- } else {
- return false;
- }
- }
-
- // We open the session
- $this->userSession->initialize($user);
- $this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id']));
-
- 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)
- {
- $ldap = $this->connect();
-
- if ($ldap !== false && $this->bind($ldap, $username, $password)) {
- return $this->getProfile($ldap, $username, $password);
- }
-
- return false;
- }
-
- /**
- * LDAP connection
- *
- * @access public
- * @return resource|boolean
- */
- public function connect()
- {
- if (! function_exists('ldap_connect')) {
- $this->logger->error('LDAP: The PHP LDAP extension is required');
- return false;
- }
-
- // Skip SSL certificate verification
- if (! LDAP_SSL_VERIFY) {
- putenv('LDAPTLS_REQCERT=never');
- }
-
- $ldap = ldap_connect($this->getLdapServer(), $this->getLdapPort());
-
- if ($ldap === false) {
- $this->logger->error('LDAP: Unable to connect to the LDAP server');
- return false;
- }
-
- ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3);
- ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0);
- ldap_set_option($ldap, LDAP_OPT_NETWORK_TIMEOUT, 1);
- ldap_set_option($ldap, LDAP_OPT_TIMELIMIT, 1);
-
- if (LDAP_START_TLS && ! @ldap_start_tls($ldap)) {
- $this->logger->error('LDAP: Unable to use ldap_start_tls()');
- return false;
- }
-
- return $ldap;
- }
-
- /**
- * LDAP authentication
- *
- * @access public
- * @param resource $ldap
- * @param string $username
- * @param string $password
- * @return boolean
- */
- public function bind($ldap, $username, $password)
- {
- if ($this->getLdapBindType() === 'user') {
- $ldap_username = sprintf($this->getLdapUsername(), $username);
- $ldap_password = $password;
- } elseif ($this->getLdapBindType() === 'proxy') {
- $ldap_username = $this->getLdapUsername();
- $ldap_password = $this->getLdapPassword();
- } else {
- $ldap_username = null;
- $ldap_password = null;
- }
-
- if (! @ldap_bind($ldap, $ldap_username, $ldap_password)) {
- $this->logger->error('LDAP: Unable to bind to server with: '.$ldap_username);
- $this->logger->error('LDAP: bind type='.$this->getLdapBindType());
- return false;
- }
-
- return true;
- }
-
- /**
- * Get LDAP user profile
- *
- * @access public
- * @param resource $ldap
- * @param string $username
- * @param string $password
- * @return boolean|array
- */
- public function getProfile($ldap, $username, $password)
- {
- $user_pattern = $this->getLdapUserPattern($username);
- $entries = $this->executeQuery($ldap, $user_pattern);
-
- if ($entries === false) {
- $this->logger->error('LDAP: Unable to get user profile: '.$user_pattern);
- return false;
- }
-
- if (@ldap_bind($ldap, $entries[0]['dn'], $password)) {
- return $this->prepareProfile($ldap, $entries, $username);
- }
-
- if (DEBUG) {
- $this->logger->debug('LDAP: wrong password for '.$entries[0]['dn']);
- }
-
- return false;
- }
-
- /**
- * Build user profile from LDAP information
- *
- * @access public
- * @param resource $ldap
- * @param array $entries
- * @param string $username
- * @return boolean|array
- */
- public function prepareProfile($ldap, array $entries, $username)
- {
- if ($this->getLdapAccountId() !== '') {
- $username = $this->getEntry($entries, $this->getLdapAccountId(), $username);
- }
-
- return array(
- 'username' => $username,
- 'name' => $this->getEntry($entries, $this->getLdapAccountName()),
- 'email' => $this->getEntry($entries, $this->getLdapAccountEmail()),
- 'is_admin' => (int) $this->isMemberOf($this->getEntries($entries, $this->getLdapAccountMemberOf()), $this->getLdapGroupAdmin()),
- 'is_project_admin' => (int) $this->isMemberOf($this->getEntries($entries, $this->getLdapAccountMemberOf()), $this->getLdapGroupProjectAdmin()),
- 'is_ldap_user' => 1,
- );
- }
-
- /**
- * Check group membership
- *
- * @access public
- * @param array $group_entries
- * @param string $group_dn
- * @return boolean
- */
- public function isMemberOf(array $group_entries, $group_dn)
- {
- if (! isset($group_entries['count']) || empty($group_dn)) {
- return false;
- }
-
- for ($i = 0; $i < $group_entries['count']; $i++) {
- if ($group_entries[$i] === $group_dn) {
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * Retrieve info on LDAP user by username or email
- *
- * @access public
- * @param string $username
- * @param string $email
- * @return boolean|array
- */
- public function lookup($username = null, $email = null)
- {
- $query = $this->getLookupQuery($username, $email);
- if ($query === '') {
- return false;
- }
-
- // Connect and attempt anonymous or proxy binding
- $ldap = $this->connect();
- if ($ldap === false || ! $this->bind($ldap, null, null)) {
- return false;
- }
-
- // Try to find user
- $entries = $this->executeQuery($ldap, $query);
- if ($entries === false) {
- return false;
- }
-
- // User id not retrieved: LDAP_ACCOUNT_ID not properly configured
- if (empty($username) && ! isset($entries[0][$this->getLdapAccountId()][0])) {
- return false;
- }
-
- return $this->prepareProfile($ldap, $entries, $username);
- }
-
- /**
- * Execute LDAP query
- *
- * @access private
- * @param resource $ldap
- * @param string $query
- * @return boolean|array
- */
- private function executeQuery($ldap, $query)
- {
- $sr = @ldap_search($ldap, $this->getLdapBaseDn(), $query, $this->getProfileAttributes());
- if ($sr === false) {
- return false;
- }
-
- $entries = ldap_get_entries($ldap, $sr);
- if ($entries === false || count($entries) === 0 || $entries['count'] == 0) {
- return false;
- }
-
- return $entries;
- }
-
- /**
- * Get the LDAP query to find a user
- *
- * @access private
- * @param string $username
- * @param string $email
- * @return string
- */
- private function getLookupQuery($username, $email)
- {
- if (! empty($username) && ! empty($email)) {
- return '(&('.$this->getLdapUserPattern($username).')('.$this->getLdapAccountEmail().'='.$email.'))';
- } elseif (! empty($username)) {
- return $this->getLdapUserPattern($username);
- } elseif (! empty($email)) {
- return '('.$this->getLdapAccountEmail().'='.$email.')';
- }
-
- return '';
- }
-
- /**
- * Return one entry from a list of entries
- *
- * @access private
- * @param array $entries LDAP entries
- * @param string $key Key
- * @param string $default Default value if key not set in entry
- * @return string
- */
- private function getEntry(array $entries, $key, $default = '')
- {
- return isset($entries[0][$key][0]) ? $entries[0][$key][0] : $default;
- }
-
- /**
- * Return subset of entries
- *
- * @access private
- * @param array $entries
- * @param string $key
- * @param array $default
- * @return array
- */
- private function getEntries(array $entries, $key, $default = array())
- {
- return isset($entries[0][$key]) ? $entries[0][$key] : $default;
- }
-}
diff --git a/app/Auth/LdapAuth.php b/app/Auth/LdapAuth.php
new file mode 100644
index 00000000..eb66e54d
--- /dev/null
+++ b/app/Auth/LdapAuth.php
@@ -0,0 +1,187 @@
+<?php
+
+namespace Kanboard\Auth;
+
+use LogicException;
+use Kanboard\Core\Base;
+use Kanboard\Core\Ldap\Client as LdapClient;
+use Kanboard\Core\Ldap\ClientException as LdapException;
+use Kanboard\Core\Ldap\User as LdapUser;
+use Kanboard\Core\Security\PasswordAuthenticationProviderInterface;
+
+/**
+ * LDAP Authentication Provider
+ *
+ * @package auth
+ * @author Frederic Guillot
+ */
+class LdapAuth extends Base implements PasswordAuthenticationProviderInterface
+{
+ /**
+ * User properties
+ *
+ * @access private
+ * @var \Kanboard\User\LdapUserProvider
+ */
+ private $user = null;
+
+ /**
+ * Username
+ *
+ * @access private
+ * @var string
+ */
+ private $username = '';
+
+ /**
+ * Password
+ *
+ * @access private
+ * @var string
+ */
+ private $password = '';
+
+ /**
+ * Get authentication provider name
+ *
+ * @access public
+ * @return string
+ */
+ public function getName()
+ {
+ return 'LDAP';
+ }
+
+ /**
+ * Authenticate the user
+ *
+ * @access public
+ * @return boolean
+ */
+ public function authenticate()
+ {
+ try {
+
+ $ldap = LdapClient::connect($this->getLdapUsername(), $this->getLdapPassword());
+ $user = LdapUser::getUser($ldap, $this->getLdapUserPattern());
+
+ if ($user === null) {
+ $this->logger->info('User not found in LDAP server');
+ return false;
+ }
+
+ if ($user->getUsername() === '') {
+ throw new LogicException('Username not found in LDAP profile, check the parameter LDAP_USER_ATTRIBUTE_USERNAME');
+ }
+
+ if ($ldap->authenticate($user->getDn(), $this->password)) {
+ $this->user = $user;
+ return true;
+ }
+
+ } catch (LdapException $e) {
+ $this->logger->error($e->getMessage());
+ }
+
+ return false;
+ }
+
+ /**
+ * Get user object
+ *
+ * @access public
+ * @return \Kanboard\User\LdapUserProvider
+ */
+ public function getUser()
+ {
+ return $this->user;
+ }
+
+ /**
+ * Set username
+ *
+ * @access public
+ * @param string $username
+ */
+ public function setUsername($username)
+ {
+ $this->username = $username;
+ }
+
+ /**
+ * Set password
+ *
+ * @access public
+ * @param string $password
+ */
+ public function setPassword($password)
+ {
+ $this->password = $password;
+ }
+
+ /**
+ * Get LDAP user pattern
+ *
+ * @access public
+ * @return string
+ */
+ public function getLdapUserPattern()
+ {
+ if (! LDAP_USER_FILTER) {
+ throw new LogicException('LDAP user filter empty, check the parameter LDAP_USER_FILTER');
+ }
+
+ return sprintf(LDAP_USER_FILTER, $this->username);
+ }
+
+ /**
+ * Get LDAP username (proxy auth)
+ *
+ * @access public
+ * @return string
+ */
+ public function getLdapUsername()
+ {
+ switch ($this->getLdapBindType()) {
+ case 'proxy':
+ return LDAP_USERNAME;
+ case 'user':
+ return sprintf(LDAP_USERNAME, $this->username);
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Get LDAP password (proxy auth)
+ *
+ * @access public
+ * @return string
+ */
+ public function getLdapPassword()
+ {
+ switch ($this->getLdapBindType()) {
+ case 'proxy':
+ return LDAP_PASSWORD;
+ case 'user':
+ return $this->password;
+ default:
+ return null;
+ }
+ }
+
+ /**
+ * Get LDAP bind type
+ *
+ * @access public
+ * @return integer
+ */
+ public function getLdapBindType()
+ {
+ if (LDAP_BIND_TYPE !== 'user' && LDAP_BIND_TYPE !== 'proxy' && LDAP_BIND_TYPE !== 'anonymous') {
+ throw new LogicException('Wrong value for the parameter LDAP_BIND_TYPE');
+ }
+
+ return LDAP_BIND_TYPE;
+ }
+}
diff --git a/app/Auth/RememberMe.php b/app/Auth/RememberMe.php
deleted file mode 100644
index 0a567cbe..00000000
--- a/app/Auth/RememberMe.php
+++ /dev/null
@@ -1,323 +0,0 @@
-<?php
-
-namespace Kanboard\Auth;
-
-use Kanboard\Core\Base;
-use Kanboard\Core\Http\Request;
-use Kanboard\Event\AuthEvent;
-use Kanboard\Core\Security\Token;
-
-/**
- * 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['expiration']
- );
-
- // Create the session
- $this->userSession->initialize($this->user->getById($record['user_id']));
-
- // Do not ask 2FA for remember me session
- $this->sessionStorage->postAuth['validated'] = true;
-
- $this->container['dispatcher']->dispatch(
- 'auth.success',
- new AuthEvent(self::AUTH_NAME, $this->userSession->getId())
- );
-
- return true;
- }
- }
-
- return false;
- }
-
- /**
- * 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.Token::getToken());
- $sequence = Token::getToken();
- $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
- * @return string
- */
- public function update($token)
- {
- $new_sequence = Token::getToken();
-
- $this->db
- ->table(self::TABLE)
- ->eq('token', $token)
- ->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,
- $this->helper->url->dir(),
- null,
- Request::isHTTPS(),
- 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,
- $this->helper->url->dir(),
- null,
- Request::isHTTPS(),
- true
- );
- }
-}
diff --git a/app/Auth/RememberMeAuth.php b/app/Auth/RememberMeAuth.php
new file mode 100644
index 00000000..02b7b9f6
--- /dev/null
+++ b/app/Auth/RememberMeAuth.php
@@ -0,0 +1,79 @@
+<?php
+
+namespace Kanboard\Auth;
+
+use Kanboard\Core\Base;
+use Kanboard\Core\Security\PreAuthenticationProviderInterface;
+use Kanboard\User\DatabaseUserProvider;
+
+/**
+ * Rember Me Cookie Authentication Provider
+ *
+ * @package auth
+ * @author Frederic Guillot
+ */
+class RememberMeAuth extends Base implements PreAuthenticationProviderInterface
+{
+ /**
+ * User properties
+ *
+ * @access private
+ * @var array
+ */
+ private $userInfo = array();
+
+ /**
+ * Get authentication provider name
+ *
+ * @access public
+ * @return string
+ */
+ public function getName()
+ {
+ return 'RememberMe';
+ }
+
+ /**
+ * Authenticate the user
+ *
+ * @access public
+ * @return boolean
+ */
+ public function authenticate()
+ {
+ $credentials = $this->rememberMeCookie->read();
+
+ if ($credentials !== false) {
+ $session = $this->rememberMeSession->find($credentials['token'], $credentials['sequence']);
+
+ if (! empty($session)) {
+ $this->rememberMeCookie->write(
+ $session['token'],
+ $this->rememberMeSession->updateSequence($session['token']),
+ $session['expiration']
+ );
+
+ $this->userInfo = $this->user->getById($session['user_id']);
+
+ return true;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Get user object
+ *
+ * @access public
+ * @return null|DatabaseUserProvider
+ */
+ public function getUser()
+ {
+ if (empty($this->userInfo)) {
+ return null;
+ }
+
+ return new DatabaseUserProvider($this->userInfo);
+ }
+}
diff --git a/app/Auth/ReverseProxy.php b/app/Auth/ReverseProxy.php
deleted file mode 100644
index d119ca98..00000000
--- a/app/Auth/ReverseProxy.php
+++ /dev/null
@@ -1,83 +0,0 @@
-<?php
-
-namespace Kanboard\Auth;
-
-use Kanboard\Core\Base;
-use Kanboard\Event\AuthEvent;
-
-/**
- * ReverseProxy backend
- *
- * @package auth
- * @author Sylvain VeyriƩ
- */
-class ReverseProxy extends Base
-{
- /**
- * Backend name
- *
- * @var string
- */
- const AUTH_NAME = 'ReverseProxy';
-
- /**
- * Get username from the reverse proxy
- *
- * @access public
- * @return string
- */
- public function getUsername()
- {
- return isset($_SERVER[REVERSE_PROXY_USER_HEADER]) ? $_SERVER[REVERSE_PROXY_USER_HEADER] : '';
- }
-
- /**
- * 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 (empty($user)) {
- $this->createUser($login);
- $user = $this->user->getByUsername($login);
- }
-
- $this->userSession->initialize($user);
- $this->container['dispatcher']->dispatch('auth.success', new AuthEvent(self::AUTH_NAME, $user['id']));
-
- 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)
- {
- $email = strpos($login, '@') !== false ? $login : '';
-
- if (REVERSE_PROXY_DEFAULT_DOMAIN !== '' && empty($email)) {
- $email = $login.'@'.REVERSE_PROXY_DEFAULT_DOMAIN;
- }
-
- return $this->user->create(array(
- 'email' => $email,
- 'username' => $login,
- 'is_admin' => REVERSE_PROXY_DEFAULT_ADMIN === $login,
- 'is_ldap_user' => 1,
- 'disable_login_form' => 1,
- ));
- }
-}
diff --git a/app/Auth/ReverseProxyAuth.php b/app/Auth/ReverseProxyAuth.php
new file mode 100644
index 00000000..8af7f0a2
--- /dev/null
+++ b/app/Auth/ReverseProxyAuth.php
@@ -0,0 +1,76 @@
+<?php
+
+namespace Kanboard\Auth;
+
+use Kanboard\Core\Base;
+use Kanboard\Core\Security\PreAuthenticationProviderInterface;
+use Kanboard\Core\Security\SessionCheckProviderInterface;
+use Kanboard\User\ReverseProxyUserProvider;
+
+/**
+ * ReverseProxy Authentication Provider
+ *
+ * @package auth
+ * @author Frederic Guillot
+ */
+class ReverseProxyAuth extends Base implements PreAuthenticationProviderInterface, SessionCheckProviderInterface
+{
+ /**
+ * User properties
+ *
+ * @access private
+ * @var \Kanboard\User\ReverseProxyUserProvider
+ */
+ private $user = null;
+
+ /**
+ * Get authentication provider name
+ *
+ * @access public
+ * @return string
+ */
+ public function getName()
+ {
+ return 'ReverseProxy';
+ }
+
+ /**
+ * Authenticate the user
+ *
+ * @access public
+ * @return boolean
+ */
+ public function authenticate()
+ {
+ $username = $this->request->getRemoteUser();
+
+ if (! empty($username)) {
+ $this->user = new ReverseProxyUserProvider($username);
+ return true;
+ }
+
+ return false;
+ }
+
+ /**
+ * Check if the user session is valid
+ *
+ * @access public
+ * @return boolean
+ */
+ public function isValidSession()
+ {
+ return $this->request->getRemoteUser() === $this->userSession->getUsername();
+ }
+
+ /**
+ * Get user object
+ *
+ * @access public
+ * @return null|ReverseProxyUserProvider
+ */
+ public function getUser()
+ {
+ return $this->user;
+ }
+}
diff --git a/app/Auth/TotpAuth.php b/app/Auth/TotpAuth.php
new file mode 100644
index 00000000..f41fabd8
--- /dev/null
+++ b/app/Auth/TotpAuth.php
@@ -0,0 +1,126 @@
+<?php
+
+namespace Kanboard\Auth;
+
+use Otp\Otp;
+use Otp\GoogleAuthenticator;
+use Base32\Base32;
+use Kanboard\Core\Base;
+use Kanboard\Core\Security\PostAuthenticationProviderInterface;
+
+/**
+ * TOTP Authentication Provider
+ *
+ * @package auth
+ * @author Frederic Guillot
+ */
+class TotpAuth extends Base implements PostAuthenticationProviderInterface
+{
+ /**
+ * User pin code
+ *
+ * @access private
+ * @var string
+ */
+ private $code = '';
+
+ /**
+ * Private key
+ *
+ * @access private
+ * @var string
+ */
+ private $secret = '';
+
+ /**
+ * Get authentication provider name
+ *
+ * @access public
+ * @return string
+ */
+ public function getName()
+ {
+ return 'Time-based One-time Password Algorithm';
+ }
+
+ /**
+ * Authenticate the user
+ *
+ * @access public
+ * @return boolean
+ */
+ public function authenticate()
+ {
+ $otp = new Otp;
+ return $otp->checkTotp(Base32::decode($this->secret), $this->code);
+ }
+
+ /**
+ * Set validation code
+ *
+ * @access public
+ * @param string $code
+ */
+ public function setCode($code)
+ {
+ $this->code = $code;
+ }
+
+ /**
+ * Set secret token
+ *
+ * @access public
+ * @param string $secret
+ */
+ public function setSecret($secret)
+ {
+ $this->secret = $secret;
+ }
+
+ /**
+ * Get secret token
+ *
+ * @access public
+ * @return string
+ */
+ public function getSecret()
+ {
+ if (empty($this->secret)) {
+ $this->secret = GoogleAuthenticator::generateRandom();
+ }
+
+ return $this->secret;
+ }
+
+ /**
+ * Get QR code url
+ *
+ * @access public
+ * @param string $label
+ * @return string
+ */
+ public function getQrCodeUrl($label)
+ {
+ if (empty($this->secret)) {
+ return '';
+ }
+
+ return GoogleAuthenticator::getQrCodeUrl('totp', $label, $this->secret);
+ }
+
+ /**
+ * Get key url (empty if no url can be provided)
+ *
+ * @access public
+ * @param string $label
+ * @return string
+ */
+ public function getKeyUrl($label)
+ {
+ if (empty($this->secret)) {
+ return '';
+ }
+
+ return GoogleAuthenticator::getKeyUri('totp', $label, $this->secret);
+ }
+}