173 lines
5.5 KiB
PHP
173 lines
5.5 KiB
PHP
<?php
|
|
|
|
class Auth {
|
|
private static $instance = null;
|
|
private $isLoggedIn = false;
|
|
|
|
private function __construct(){
|
|
session_start();
|
|
}
|
|
|
|
public static function getInstance(): Auth {
|
|
if(self::$instance == null){
|
|
self::$instance = new Auth();
|
|
}
|
|
|
|
return self::$instance;
|
|
}
|
|
|
|
public static function loginWithCredentials($email, $pass, bool $stayLoggedIn = false){
|
|
$Auth = new Auth();
|
|
|
|
$err = [];
|
|
|
|
// get user from database
|
|
$getUserSQL = "SELECT pwd, user_id, user_email FROM user WHERE user_email = ? LIMIT 1;";
|
|
$getUserRes = DB::query($getUserSQL, $email);
|
|
|
|
$dbPass = "missingPassword";
|
|
$dbUserId = 0;
|
|
$dbUserName = "Unknown";
|
|
|
|
if($getUserRes->num_rows == 1){
|
|
// Verify password
|
|
list($dbPass, $dbUserId, $dbUserName) = $getUserRes->fetch_row();
|
|
}
|
|
|
|
if(password_verify(PwdGen($pass), $dbPass)){
|
|
session_regenerate_id();
|
|
|
|
$md5agent = md5($_SERVER['HTTP_USER_AGENT']);
|
|
$userKey = GenKey();
|
|
$shaUserKey = sha1($userKey);
|
|
$expire = $stayLoggedIn?30:0; // if "stay logged in", stay logged in for 30 days.
|
|
|
|
$updateUserSQL = "INSERT INTO user_login (user_id, ckey, ctime, expire, agent) VALUES (?, ?, ?, ?, ?);";
|
|
if(DB::query($updateUserSQL, $dbUserId, $userKey, time(), $expire, $md5agent)){
|
|
$_SESSION['user_id'] = $dbUserId;
|
|
$_SESSION['user_name'] = $dbUserName;
|
|
$_SESSION['user_agent'] = $md5agent;
|
|
$_SESSION['user_key'] = $shaUserKey;
|
|
|
|
if($stayLoggedIn){
|
|
setcookie("auth", $shaUserKey.".".$dbUserId, time() + (30 * 24*60*60), "/", $_SERVER['HTTP_HOST'], isset($_SERVER['HTTPS']), true );
|
|
}
|
|
return true;
|
|
}
|
|
else {
|
|
$err[] = "Failed to login.\n".$db->error;
|
|
}
|
|
}
|
|
else {
|
|
$err[] = "Username and/or Password is wrong.";
|
|
}
|
|
|
|
return $err;
|
|
}
|
|
|
|
|
|
public static function loginFromAuthKey(): bool {
|
|
if(isset($_COOKIE['auth'])){
|
|
$md5agent = md5($_SERVER['HTTP_USER_AGENT']);
|
|
|
|
$cookieSplode = explode('.', $_COOKIE['auth']);
|
|
if(count($cookieSplode) == 2){
|
|
$tkey = $cookieSplode[0];
|
|
$tuid = $cookieSplode[1];
|
|
$verifyLoginCookieRes = DB::query("
|
|
SELECT ul.user_id, ul.ckey, ul.ctime, ul.expire, ul.agent, u.full_name
|
|
FROM user_login ul
|
|
INNER JOIN user u ON ul.user_id = u.user_id
|
|
WHERE ul.user_id = ?
|
|
ORDER BY ctime DESC", $tuid);
|
|
while($row = $verifyLoginCookieRes->fetch_assoc()){
|
|
if($row['expire'] == 0){ $row['expire'] = 1; }
|
|
if(
|
|
sha1($row['ckey']) == $tkey &&
|
|
$row['agent'] == $md5agent &&
|
|
($row['ctime']+($row['expire']*24*60*60) > time())
|
|
){
|
|
session_regenerate_id();
|
|
$_SESSION['user_id'] = $row['user_id'];
|
|
$_SESSION['user_name'] = $row['full_name'];
|
|
$_SESSION['user_agent'] = $md5agent;
|
|
$_SESSION['user_key'] = sha1($row['ckey']);
|
|
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public static function logout(){}
|
|
|
|
|
|
public static function checkLogin($strict = false): bool {
|
|
$Auth = Auth::getInstance();
|
|
|
|
if(
|
|
($Auth->isLoggedIn && !$strict) ||
|
|
$Auth->checkSessionLogin() ||
|
|
$Auth->loginFromAuthKey()
|
|
) {
|
|
return true;
|
|
}
|
|
|
|
unset($_SESSION['user_id']);
|
|
return false;
|
|
}
|
|
|
|
private function checkSessionLogin(): bool {
|
|
if(isset($_SESSION['user_id'])){
|
|
$md5agent = md5($_SERVER['HTTP_USER_AGENT']);
|
|
if($md5agent == @$_SESSION['user_agent']){
|
|
$verifyLoginSessionRes = DB::query("
|
|
SELECT expire, ctime, ckey
|
|
FROM `user_login`
|
|
WHERE user_id = ?
|
|
AND agent = ?",
|
|
$_SESSION['user_id'], $md5agent);
|
|
|
|
while ($row = $verifyLoginSessionRes->fetch_assoc()){
|
|
if(
|
|
(sha1($row['ckey']) == $_SESSION['user_key']) &&
|
|
($row['expire'] == 0 || $row['ctime']+($row['expire']*24*60*60) > time())
|
|
){
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
function PwdGen($pass, $returnHashed = false): string {
|
|
$pepper = Config::get('security', 'pepper', 'IAmBadAtSecurity');
|
|
$pwd_peppered = hash_hmac("sha256", $pass, $pepper);
|
|
if(!$returnHashed){
|
|
return $pwd_peppered;
|
|
}
|
|
|
|
return password_hash($pwd_peppered, PASSWORD_ARGON2ID, ['threads' => 2]);
|
|
}
|
|
|
|
function GenKey($length = 21): string{
|
|
$password = "";
|
|
$possible = "0123456789abcdefghijkmnopqrstuvwxyz";
|
|
|
|
$i = 0;
|
|
|
|
while($i < $length){
|
|
$char = substr($possible, mt_rand(0, strlen($possible)-1), 1);
|
|
|
|
if(!strstr($password, $char)){
|
|
$password .= $char;
|
|
$i++;
|
|
}
|
|
}
|
|
|
|
return $password;
|
|
} |