PaperBag/application/Auth.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;
}