Files
DomFramework/src/Authsql.php
2022-11-25 21:21:30 +01:00

295 lines
10 KiB
PHP

<?php
/** DomFramework
* @package domframework
* @author Dominique Fournier <dominique@fournier38.fr>
* @license BSD
*/
namespace Domframework;
/** User authentication against SQL database */
class Authsql extends Auth
{
/** The DSN to use to connect to SQL database */
public $dsn = null;
/** The username to connect to the database */
public $username = null;
/** The password to use to connecto to the database */
public $password = null;
/** The driver options for the PDO driver */
public $driver_options = null;
/** The table name to use */
public $table = null;
/** The tableprefix text to prepend to table name (Should finish by _)
Just allow chars ! */
public $tableprefix = "";
/** The password field name */
public $fieldPassword = "password";
/** The identifier field name (maybe email) */
public $fieldIdentifier = "email";
/** The field name containing the lastname of the user */
public $fieldLastname = null;
/** The field name containing the Firstname of the user */
public $fieldFirstname = null;
/** The information fields (in an array) */
public $fieldsInfo = array();
/** The DBLayer pointer */
private $db = null;
/** The details of the authenticated user */
private $details = null;
/** Establish a connection to a SQL server */
public function connect()
{
if (! function_exists("openssl_random_pseudo_bytes")) {
throw new \Exception(
dgettext(
"domframework",
"No PHP support for openssl_random_pseudo_bytes"
),
500
);
}
$this->db = new Dblayer(
$this->dsn,
$this->username,
$this->password,
$this->driver_options
);
if ($this->table === null) {
throw new \Exception(
dgettext("domframework", "No SQL table defined"),
500
);
}
if ($this->fieldIdentifier === null) {
throw new \Exception(dgettext(
"domframework",
"No fieldIdentifier defined"
), 500);
}
if ($this->fieldPassword === null) {
throw new \Exception(dgettext(
"domframework",
"No fieldPassword defined"
), 500);
}
if ($this->fieldLastname === null) {
throw new \Exception(dgettext(
"domframework",
"No fieldLastname defined"
), 500);
}
if ($this->fieldFirstname === null) {
throw new \Exception(dgettext(
"domframework",
"No fieldFirstname defined"
), 500);
}
$fields = array_merge(
array($this->fieldIdentifier, $this->fieldPassword,
$this->fieldLastname, $this->fieldFirstname),
$this->fieldsInfo
);
$fields = array_flip($fields);
foreach ($fields as $key => $val) {
$fields[$key] = array("varchar", "255");
}
$this->db->table = $this->table;
$this->db->fields = $fields;
$this->db->primary = $this->fieldIdentifier;
}
/** Try to authenticate the email/password of the user
@param string $email Email to authenticate
@param string $password Password to authenticate */
public function authentication($email, $password)
{
if ($this->db === null) {
throw new \Exception(dgettext(
"domframework",
"The SQL database is not connected"
), 500);
}
$data = $this->db->read(
array(array($this->fieldIdentifier, $email)),
array_merge(
array($this->fieldIdentifier,
$this->fieldFirstname,
$this->fieldLastname,
$this->fieldPassword),
$this->fieldsInfo
)
);
if (count($data) === 0) {
throw new \Exception(sprintf(
dgettext(
"domframework",
"Unable to find the user : '%s'"
),
$email
), 401);
}
if (! isset($data[0][$this->fieldPassword])) {
throw new \Exception(
dgettext(
"domframework",
"Unable to get the user password from database"
),
500
);
}
$cryptedPassword = $data[0][$this->fieldPassword];
if (crypt($password, $cryptedPassword) !== $cryptedPassword) {
throw new \Exception(
sprintf(dgettext(
"domframework",
"Bad password for '%s'"
), $email),
401
);
}
// The password should never be stored by this function
unset($data[0][$this->fieldPassword]);
$content = $data[0];
$content["email"] = $data[0][$this->fieldIdentifier];
$content["lastname"] = $data[0][$this->fieldLastname];
$content["firstname"] = $data[0][$this->fieldFirstname];
$this->details = $content;
}
/** Return all the parameters recorded for the authenticate user */
public function getdetails()
{
return $this->details;
}
/** Method to change the password
@param string $oldpassword The old password (to check if the user have the
rights to change the password)
@param string $newpassword The new password to be recorded */
public function changepassword($oldpassword, $newpassword)
{
if ($this->db === null) {
throw new \Exception(dgettext(
"domframework",
"The SQL database is not connected"
), 500);
}
if (
$this->details === null ||
! isset($this->details[$this->fieldIdentifier])
) {
throw new \Exception(
dgettext(
"domframework",
"Can't change the password if the user is not authenticated"
),
500
);
}
$data = $this->db->read(
array(array($this->fieldIdentifier,
$this->details[$this->fieldIdentifier])),
array($this->fieldIdentifier,
$this->fieldPassword)
);
$cryptedPassword = $data[0][$this->fieldPassword];
if (crypt($oldpassword, $cryptedPassword) !== $cryptedPassword) {
throw new \Exception(dgettext(
"domframework",
"Bad old password provided"
), 401);
}
$cost = 11;
$salt = substr(base64_encode(openssl_random_pseudo_bytes(17)), 0, 22);
$salt = str_replace("+", ".", $salt);
$param = '$' . implode('$', array(
"2y", //select the most secure version of blowfish (>=PHP 5.3.7)
str_pad($cost, 2, "0", STR_PAD_LEFT), //add the cost in two digits
$salt //add the salt
));
//now do the actual hashing
$cryptpassword = crypt($newpassword, $param);
$rc = $this->db->update(
$this->details[$this->fieldIdentifier],
array($this->fieldPassword => $cryptpassword)
);
if ($rc !== 1) {
throw new \Exception(dgettext(
"domframework",
"Can't change the password"
), 500);
}
}
/** Method to overwrite the password (without oldpassword check)
Must be reserved to the administrators. For the users, use changepassword
method
@param string $email the user identifier to select
@param string $newpassword The new password to be recorded */
public function overwritepassword($email, $newpassword)
{
if ($this->db === null) {
throw new \Exception(dgettext(
"domframework",
"The SQL database is not connected"
), 500);
}
$data = $this->db->read(
array(array($this->fieldIdentifier, $email)),
array($this->fieldIdentifier,
$this->fieldPassword)
);
if (count($data) === 0) {
throw new \Exception(sprintf(
dgettext(
"domframework",
"Unable to find the user : '%s'"
),
$email
), 401);
}
$cost = 11;
$salt = substr(base64_encode(openssl_random_pseudo_bytes(17)), 0, 22);
$salt = str_replace("+", ".", $salt);
$param = '$' . implode('$', array(
"2y", //select the most secure version of blowfish (>=PHP 5.3.7)
str_pad($cost, 2, "0", STR_PAD_LEFT), //add the cost in two digits
$salt //add the salt
));
//now do the actual hashing
$cryptpassword = crypt($newpassword, $param);
$rc = $this->db->update(
$email,
array($this->fieldPassword => $cryptpassword)
);
if ($rc !== 1) {
throw new \Exception(dgettext(
"domframework",
"Can't change the password"
), 500);
}
}
/** List all the users available in the database
Return firstname, lastname, mail, with mail is an array */
public function listusers()
{
if ($this->db === null) {
throw new \Exception(dgettext(
"domframework",
"The SQL database is not connected"
), 500);
}
$data = $this->db->read(null, array_merge(
array($this->fieldIdentifier,
$this->fieldFirstname,
$this->fieldLastname),
$this->fieldsInfo
));
return $data;
}
}