owncloud-archive / apps

Repo for ownCloud apps. Code here is work in progress and not intended for endusers
373 stars 337 forks source link

How to extend user_external? #2168

Open alexschomb opened 8 years ago

alexschomb commented 8 years ago

What is the recommended way to extend user_external with additional authentication methods? Copy & rename?

I just implemented an external MySQL authentication. Please note that the code is working, but pretty dirty.

# /config/config.php
  'user_backends' => array (
    0 => array (
      'class' => 'OC_User_MySQL',
      'arguments' => array (
        0 => 'mysql.example.com',
        1 => 3306,
        2 => 'database',
        3 => 'owncloud',
        4 => 'MySecurePassword',
        5 => 'SELECT id FROM users WHERE name = ? AND password = PASSWORD(?);',
      ),
    ),
  ),
  'lost_password_link' => 'https://example.com/reset-password',
# /apps/user_external/appinfo/app.php
<?php
OC::$CLASSPATH['OC_User_IMAP']='user_external/lib/imap.php';
OC::$CLASSPATH['OC_User_SMB']='user_external/lib/smb.php';
OC::$CLASSPATH['OC_User_FTP']='user_external/lib/ftp.php';
OC::$CLASSPATH['OC_User_MySQL']='user_external/lib/mysql.php';
# /apps/user_external/lib/mysql.php
<?php
/**
 * Copyright (c) 2016 Robin Appelman <icewind@owncloud.com>
 * This file is licensed under the Affero General Public License version 3 or
 * later.
 * See the COPYING-README file.
 */

/**
 * User authentication against a MySQL server
 *
 * @category Apps
 * @package  UserExternal
 * @author   Robin Appelman <icewind@owncloud.com>
 * @license  http://www.gnu.org/licenses/agpl AGPL
 * @link     http://github.com/owncloud/apps
 */
class OC_User_MySQL extends \OCA\user_external\Base {
    private $host;
    private $port;
    private $db_name;
    private $db_user;
    private $db_password;
    private $query;

    /**
     * Create new MySQL authentication provider
     *
     * @param string  $host   Hostname or IP of MySQL server
     * @param integer $port Port of MySQL server
     * @param string $db_name Name of database
     * @param string $db_user Username
     * @param string $db_password Password
     * @param string $query SQL query that checks password
     *                      use $uid and $password inside query
     */
    public function __construct($host,$port=3306,$db_name,$db_user,$db_password,$query) {
        parent::__construct($host,$port,$db_name,$db_user,$db_password,$query);
        $this->host=$host;
        $this->port=$port;
        $this->db_name=$db_name;
        $this->db_user=$db_user;
        $this->db_password=$db_password;
        $this->query=$query;
    }

    /**
     * Check if the password is correct without logging in the user
     *
     * @param string $uid      The username
     * @param string $password The password
     *
     * @return true/false
     */
    public function checkPassword($uid, $password) {
        try {
            $db = new PDO("mysql:host=".$this->host.";port=".$this->port.";dbname=".$this->db_name,$this->db_user,$this->db_password);
            $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_WARNING);
            $db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_OBJ);
            $db->setAttribute(PDO::MYSQL_ATTR_INIT_COMMAND,'SET NAMES UTF8');
            $query = $db->prepare($this->query);
            $result = $query->execute(array(
                $uid,
                $password
            ));
            if(! $result) {
                \OCP\Util::writeLog('OC_User_MySQL', 'ERROR: MySQL query failed.');
                return false;
            } else {
                $row_count = $query->rowCount();
                if($row_count > 0) {
                    $this->storeUser($uid);
                    return $uid;
                } else {
                    return false;
                }
            }
        } catch(PDOException $e) {
            \OCP\Util::writeLog('OC_User_MySQL', 'ERROR: '.$e->getMessage());
            return false;
        }
    }
}
alexschomb commented 8 years ago

@icewind1991 Can you help?

PVince81 commented 7 years ago

If you are providing a new authentication method then yes it makes sense to create a new folder for it. Whether you wrote it from scratch or copied another method and adjusted it doesn't make any difference.