4
\$\begingroup\$

I am going to use the following class which is very simple to use and get user info in pages:

<?php
ini_set("display_errors", "on");

class LoginSystem {

    /* Start Config */
    private $dbhost = "localhost"; // Host Name
    private $dbport = "8889"; //Port
    private $dbuser = "root"; // MySQL Database Username
    private $dbpass = "root"; // MySQL Database Password
    private $dbname = "database"; // Database Name
    private $dbtable = "users"; // Your Users Table

    private $secureKey    = "secureKey"; // A Secure Key For Cookie Encryption. Don't make this public
    private $passwordSalt = "secureSalt"; // Secret Password Salt. Only change once before setting user registration public.
    private $company      = "http://***.com"; // Company for name for including in emails

    var $phpsessionstart    = true; // Should I Start A PHP Session
    var $emailLogin         = true; // Make Login With Username & E-Mail Possible
    var $rememberMe         = true; // Add Remember Me Feature.
    var $blockBruteForce    = true; // Deny login for $LS->bfTime seconds after incorrect login tries of 5

        /* Extra Settings*/

            // Set the following variables only if you're going to use $LS->init()
            private $staticPages    = array(
                "/php/loginSystem/", "/php/loginSystem/reset.php"
            ); // Pages that doesn't require logging in (exclude login page)

            private $loginPage      = "/php/loginSystem/login.php"; // The login page. ex : /login.php or /accounts/login.php
            private $homePage       = "/php/loginSystem/home.php"; // The home page. The main page for logged in users. Redirects to here when logs in
            public $bfTime          = 300; // The time IN SECONDS for which block from login action should be done after 5 incorrect login attempts. Use http://www.easysurf.cc/utime.htm#m60s for converting minutes to seconds. Default : 5 minutes

    /* End Config */

    public $loggedIn        = false;
    public $db              = true;
    public $user            = false;
    private $initCalled     = false;
    private $cookie;
    private $session;
    private $remCook;
    private $dbh;

    public function __construct(){
        if($this->phpsessionstart == true){
            session_start();
        }

        /* Try connecting to Database Server */
        try{
            /* Merge the login page to the pages array that doesn't need logging in */
            array_push($this->staticPages, $this->loginPage);

            $this->dbh      = new PDO("mysql:dbname={$this->dbname};host={$this->dbhost};port={$this->dbport}", $this->dbuser, $this->dbpass);
            $this->db       = true;
            $this->cookie   = isset($_COOKIE['logSyslogin']) ? $_COOKIE['logSyslogin'] : false;
            $this->session  = isset($_SESSION['logSyscuruser']) ? $_SESSION['logSyscuruser'] : false;
            $this->remCook  = isset($_COOKIE['logSysrememberMe']) ? $_COOKIE['logSysrememberMe'] : false;

            $encUserID      = hash("sha256", "{$this->secureKey}{$this->session}{$this->secureKey}");
            $this->loggedIn = $this->cookie == $encUserID ? true : false;

            /* If there is a Remember Me Cookie and the user is not logged in, then log in the user with the ID in the remember cookie, if it matches with the secure hashed value in logSyslogin cookie */
            if($this->rememberMe === true && isset($this->remCook) && $this->loggedIn === false){

                $encUserID      = hash("sha256", "{$this->secureKey}{$this->remCook}{$this->secureKey}");
                $this->loggedIn = $this->cookie == $encUserID ? true : false;

                if($this->loggedIn === true){
                    $_SESSION['logSyscuruser'] = $this->remCook;
                }
            }

            $this->user = $this->session;
            return true;

        }catch( PDOException $e ) {
            return false;
        }
    }

    /* A function that will automatically redirect user according to his/her login status */
    public function init() {
        if( $this->loggedIn && array_search($this->curPage(), $this->staticPages) !== false ){
            $this->redirect($this->homePage);
        }elseif( !$this->loggedIn && array_search($this->curPage(), $this->staticPages) === false ){
            $this->redirect($this->loginPage);
        }
        $this->initCalled = true;
    }

    /* A function to login the user with the username and password given. */
    public function login($username, $password, $cookies = true){
        if($this->db === true){

            /* We Add LIMIT to 1 in SQL query because we need to just get an array of data with key as the column name. Nothing else. */
            if($this->emailLogin === true){
                $query = "SELECT `id`, `password`, `password_salt`, `attempt` FROM `{$this->dbtable}` WHERE `username`=:login OR `email`=:login ORDER BY `id` LIMIT 1";
            }else{
                $query = "SELECT `id`, `password`, `password_salt`, `attempt` FROM `{$this->dbtable}` WHERE `username`=:login ORDER BY `id` LIMIT 1";
            }

            $sql = $this->dbh->prepare($query);
            $sql->bindValue(":login", $username);
            $sql->execute();

            if($sql->rowCount() == 0){
                // No such user like that
                return false;
            }else{
                /* Get the user details */
                $rows       = $sql->fetch(PDO::FETCH_ASSOC);
                $us_id      = $rows['id'];
                $us_pass    = $rows['password'];
                $us_salt    = $rows['password_salt'];
                $status     = $rows['attempt'];
                $saltedPass = hash('sha256', "{$password}{$this->passwordSalt}{$us_salt}");

                if(substr($status, 0, 2) == "b-"){
                    $blockedTime = substr($status, 2);
                    if(time() < $blockedTime){
                        $block = true;
                        return array(
                            "status"    => "blocked",
                            "minutes"   => round(abs($blockedTime - time()) / 60, 0),
                            "seconds"   => round(abs($blockedTime - time()) / 60*60, 2)
                        );
                    }else{
                        // remove the block, because the time limit is over
                        $this->updateUser(array(
                            "attempt" => "" // No tries at all
                        ), $us_id);
                    }
                }
                if(!isset($block) && ($saltedPass == $us_pass || $password == "")){
                    if($cookies === true){

                        $_SESSION['logSyscuruser'] = $us_id;
                        setcookie("logSyslogin", hash("sha256", $this->secureKey.$us_id.$this->secureKey), time()+3600*99*500, "/");

                        if( isset($_POST['remember_me']) && $this->rememberMe === true ){
                            setcookie("logSysrememberMe", $us_id, time()+3600*99*500, "/");
                        }
                        $this->loggedIn = true;

                        // Update the attempt status
                        $this->updateUser(array(
                            "attempt" => "" // No tries
                        ), $us_id);

                        // Redirect
                        if( $this->initCalled ){
                            $this->redirect($this->homePage);
                        }
                    }
                    return true;
                }else{
                    // Incorrect password
                    if($this->blockBruteForce === true){
                        // Checking for brute force is enabled
                        if($status == ""){
                            // User was not logged in before
                            $this->updateUser(array(
                                "attempt" => "1" // Tried 1 time
                            ), $us_id);
                        }else if($status == 5){
                            $this->updateUser(array(
                                "attempt" => "b-" . strtotime("+{$this->bfTime} seconds", time()) // Blocked, only available for re-login at the time in UNIX timestamp
                            ), $us_id);
                        }else if(substr($status, 0, 2) == "b-"){
                            // Account blocked
                        }else if($status < 5){
                            // If the attempts are less than 5 and not 5
                            $this->updateUser(array(
                                "attempt" => $status + 1 // Tried current tries + 1 time
                            ), $us_id);
                        }
                    }
                    return false;
                }
            }
        }
    }

    /* A function to register a user with passing the username, password and optionally any other additional fields. */
    public function register( $id, $password, $other = array() ){
        if( $this->userExists($id) && (isset($other['email']) && $this->userExists($other['email'])) ){
            return "exists";
        }else{
            $randomSalt = $this->rand_string(20);
            $saltedPass = hash('sha256', "{$password}{$this->passwordSalt}{$randomSalt}");

            if( count($other) == 0 ){
                /* If there is no other fields mentioned, make the default query */
                $sql = $this->dbh->prepare("INSERT INTO `{$this->dbtable}` (`username`, `password`, `password_salt`) VALUES(:username, :password, :passwordSalt)");
            }else{
                /* if there are other fields to add value to, make the query and bind values according to it */
                $keys    = array_keys($other);
                $columns = implode(",", $keys);
                $colVals = implode(",:", $keys);
                $sql     = $this->dbh->prepare("INSERT INTO `{$this->dbtable}` (`username`, `password`, `password_salt`, $columns) VALUES(:username, :password, :passwordSalt, :$colVals)");
                foreach($other as $key => $value){
                    $value = htmlspecialchars($value);
                    $sql->bindValue(":$key", $value);
                }
            }
            /* Bind the default values */
            $sql->bindValue(":username", $id);
            $sql->bindValue(":password", $saltedPass);
            $sql->bindValue(":passwordSalt", $randomSalt);
            $sql->execute();
            return true;
        }
    }

    /* Logout the current logged in user by deleting the cookies and destroying session */
    public function logout(){
        session_destroy();
        setcookie("logSyslogin", "", time()-3600, "/");
        setcookie("logSysrememberMe", "", time()-3600, "/");
        $this->redirect($this->loginPage);
        return true;
    }

    /* A function to handle the Forgot Password process */
    public function forgotPassword(){

        $curStatus = "initial"; // The Current Status of Forgot Password process
        $identName = $this->emailLogin === false ? "Username" : "Username / E-Mail";

        if( !isset($_POST['logSysforgotPass']) && !isset($_GET['resetPassToken']) && !isset($_POST['logSysforgotPassRePass']) ){
            $html='<form action="'.$_SERVER['PHP_SELF'].'" method="POST">';
                $html.="<label>$identName<br/><input type='text' id='loginSysIdentification' placeholder='Enter your $identName' size='25' name='identification'/></label>";
                $html.="<br/><button name='logSysforgotPass' type='submit'>Reset Password</button>";
            $html.="</form>";
            echo $html;
            $curStatus = "resetPasswordForm"; // The user had moved to the reset password form ie she/he is currently seeing the forgot password form.

        }elseif( isset($_GET['resetPassToken']) && !isset($_POST['logSysforgotPassRePass']) ){
            /* The user gave the password reset token. Check if the token is valid. */
            $_GET['resetPassToken'] = urldecode($_GET['resetPassToken']);
            $sql = $this->dbh->prepare("SELECT `uid` FROM `resetTokens` WHERE `token` = ?");
            $sql->execute(array($_GET['resetPassToken']));

            if( $sql->rowCount() == 0 || $_GET['resetPassToken'] == "" ){
                echo "<h3>Error : Wrong/Invalid Token</h3>";
                $curStatus = "invalidToken"; // The token user gave was not valid
            }else{
                /* The token is valid, display the new password form */
                $html  = "<p>The Token key was Authorized. Now, you can change the password</p>";
                $html .= "<form action='{$_SERVER['PHP_SELF']}' method='POST'>";
                    $html   .=  "<input type='hidden' name='token' value='{$_GET['resetPassToken']}'/>";
                    $html   .=  "<label>New Password<br/><input type='password' name='password'/></label><br/>";
                    $html   .=  "<label>Retype Password<br/><input type='password' name='password2'/></label><br/>";
                    $html   .=  "<button name='logSysforgotPassRePass'>Reset Password</button>";
                $html   .=  "</form>";
                echo $html;
                $curStatus = "changePasswordForm"; // The token was correct, displayed the change/new password form.
            }
        }elseif( isset($_POST['logSysforgotPassRePass']) ){
            $_POST['token'] = urldecode($_POST['token']);
            $sql = $this->dbh->prepare("SELECT `uid` FROM `resetTokens` WHERE `token` = ?");
            $sql->execute(array($_POST['token']));

            if( $sql->rowCount()==0 || $_POST['token']=="" ){
                echo "<h3>Error : Wrong/Invalid Token</h3>";
                $curStatus = "invalidToken"; // The token user gave was not valid
            }else{
                if( $_POST['password'] != $_POST['password2'] || $_POST['password']=="" || $_POST['password2']=="" ){
                    echo "<h3>Error : Passwords Don't Match Or Passwords Left Blank</h3>";
                    $curStatus = "passwordDontMatch"; // The new password and retype password submitted didn't match
                }else{

                    $_POST['newPassword'] = $_POST['password2'];
                    $this->user           = $sql->fetchColumn();
                    $this->loggedIn       = true; // We must create a fake assumption that the user is logged in to change the password as $LS->changePassword() requires the user to be logged in.

                    if( $this->changePassword($this->secureKey) ){
                        $this->user     = false;
                        $this->loggedIn = false;
                        $sql            = $this->dbh->prepare("DELETE FROM resetTokens WHERE token=?");
                        $sql->execute(array($_POST['token']));
                        echo "<h3>Success : Password Reset Successful</h3><p>You may now login with your new password.</p>";
                        $curStatus = "passwordChanged"; // The password was successfully changed
                    }
                }
            }
        }else{
            /* Check if username/email is provided and if it's valid and exists */
            $identification = isset($_POST['identification']) ? $_POST['identification']:"";
            if($identification == ""){
                echo "<h3>Error : $identName not provided</h3>";
                $curStatus = "identityNotProvided"; // The identity was not given
            }else{
                $sql = $this->dbh->prepare("SELECT `email`, `id` FROM `{$this->dbtable}` WHERE `username`=:login OR `email`=:login");
                $sql->bindValue(":login", $identification);
                $sql->execute();
                if($sql->rowCount() == 0){
                    echo "<h3>Error : User Not Found</h3>";
                    $curStatus = "userNotFound"; // The user with the identity given was not found in the users database
                }else{
                    $rows  = $sql->fetch(PDO::FETCH_ASSOC);
                    $email = $rows['email'];
                    $uid   = $rows['id'];
                    $token = $this->rand_string(40);
                    $sql   = $this->dbh->prepare("INSERT INTO `resetTokens` (`token`, `uid`, `requested`) VALUES (?, ?, NOW())");
                    $sql->execute(array($token, $uid));
                    $encodedToken = urlencode($token);

                    /* Prepare the email to be sent */
                    $subject = "Reset Password";
                    $body    = "You requested for resetting your password on {$this->company}. For this, please click the following link :
                    <blockquote>
                        <a href='{$this->curPageURL()}?resetPassToken={$encodedToken}'>Reset Password : {$token}</a>
                    </blockquote>";
                    $this->sendMail($email, $subject, $body);   /* Change mail() function to something else if you like */
                    echo "<p>An email has been sent to your email inbox with instructions. Check Your Mail Inbox and SPAM Folders.</p><p>You can close this window.</p>";
                    $curStatus = "emailSent"; // E-Mail has been sent
                }
            }
        }
        return $curStatus;
    }

    /* A function that handles the logged in user to change her/his password */
    public function changePassword($parent = ""){
        $curStatus = "initial"; // The Current Status of Change Password action
        if($this->loggedIn){
            if( $parent == $this->secureKey && isset($_POST['newPassword']) && $_POST['newPassword'] != "" ){
                $randomSalt = $this->rand_string(20);
                $saltedPass = hash('sha256',$_POST['newPassword'].$this->passwordSalt.$randomSalt);
                $sql        = $this->dbh->prepare("UPDATE `{$this->dbtable}` SET `password` = ?, `password_salt` = ? WHERE `id` = ?");
                $sql->execute(array($saltedPass, $randomSalt, $this->user));
                return true;
            }elseif( !isset($_POST['logSysChangePassword']) ){
                $html = "<form action='".$_SERVER['PHP_SELF']."' method='POST'>";
                    $html .= "<label>Current Password<br/><input type='password' name='curpass'/></label><br/>";
                    $html .= "<label>New Password<br/><input type='password' name='newPassword'/></label><br/>";
                    $html .= "<label>Retype New Password<br/><input type='password' name='newPassword2'/></label><br/>";
                    $html .= "<button name='logSysChangePassword' type='submit'>Change Password</button>";
                $html .= "</form>";
                echo $html;
                $curStatus = "changePasswordForm"; // The form for changing password is shown now
            }elseif(isset($_POST['logSysChangePassword'])){
                if( isset($_POST['newPassword']) && $_POST['newPassword']!="" && isset($_POST['newPassword2']) && $_POST['newPassword2']!="" && isset($_POST['curpass']) && $_POST['curpass']!="" ){
                    $curpass      = $_POST['curpass'];
                    $newPassword  = $_POST['newPassword'];
                    $newPassword2 = $_POST['newPassword2'];
                    $sql          = $this->dbh->prepare("SELECT username FROM `{$this->dbtable}` WHERE id=?");
                    $sql->execute(array($this->user));
                    $curuserUsername = $sql->fetchColumn();
                    if($this->login($curuserUsername, $curpass, false)){
                        if($newPassword != $newPassword2){
                            echo "<h3>Error : Password Mismatch</h3>";
                            $curStatus = "newPasswordMismatch"; // The Password's don't match (New Password & Retype Password field)
                        }else{
                            $this->changePassword($this->secureKey);
                            echo "<h3>Success : Password Changed Successful</h3>";
                            $curStatus = "passwordChanged"; // Password changed
                        }
                    }else{
                        echo "<h3>Error : Current Password Was Wrong</h3>";
                        $curStatus = "currentPasswordWrong"; // The current password entered was wrong
                    }
                }else{
                    echo "<h3>Error : Password Fields was blank</h3>";
                    $curStatus = "newPasswordFieldsBlank"; // Blank new password field
                }
            }
        }else{
            echo "<h3>Error : Not Logged In</h3>";
            $curStatus = "notLoggedIn"; // Not logged In
        }
        return $curStatus;
    }

    /* Check if user exists with ther username/email given */
    public function userExists($username){
        if($this->emailLogin === true){
            $query = "SELECT `id` FROM `{$this->dbtable}` WHERE `username`=:login OR `email`=:login ORDER BY `id` LIMIT 1";
        }else{
            $query = "SELECT `id` FROM `{$this->dbtable}` WHERE `username`=:login ORDER BY `id` LIMIT 1";
        }
        $sql = $this->dbh->prepare($query);
        $sql->execute(array(
            ":login" => $username
        ));
        return $sql->rowCount() == 0 ? false : true;
    }

    /* Fetches data of user in database. Returns a single value or an array of value according to parameteres given to the function */
    public function getUser($what = "*", $user = null){
        if($user == null){
            $user = $this->user;
        }
        if( is_array($what) ){
            $columns = implode("`,`", $what);
            $columns    = "`{$columns}`";
        }else{
            $columns = $what != "*" ? "`$what`" : "*";
        }

        $sql = $this->dbh->prepare("SELECT {$columns} FROM `{$this->dbtable}` WHERE `id`=? ORDER BY `id` LIMIT 1");
        $sql->execute(array($user));

        $data = $sql->fetch(PDO::FETCH_ASSOC);
        if( !is_array($what) ){
            $data = $what == "*" ? $data : $data[$what];
        }
        return $data;
    }

    /* Updates the user data */
    public function updateUser($toUpdate = array(), $user = null){
        if( is_array($toUpdate) && !isset($toUpdate['id']) ){
            if($user == null){
                $user = $this->user;
            }
            $columns = "";
            foreach($toUpdate as $k => $v){
                $columns .= "`$k` = :$k, ";
            }
            $columns = substr($columns, 0, -2); // Remove last ","

            $sql = $this->dbh->prepare("UPDATE `{$this->dbtable}` SET {$columns} WHERE `id`=:id");
            $sql->bindValue(":id", $user);
            foreach($toUpdate as $key => $value){
                    $value = htmlspecialchars($value);
                    $sql->bindValue(":$key", $value);
                }
            $sql->execute();

        }else{
            return false;
        }
    }

    /* Returns a string which shows the time since the user has joined */
    public function timeSinceJoin($user = null){
        if($user == null){
            $user = $this->user;
        }
        $created    = $this->getUser("created");
        $timeFirst  = strtotime($created);
        $timeSecond = strtotime("now");
        $memsince   = $timeSecond - strtotime($created);
        $regged         = date("n/j/Y", strtotime($created));

        if($memsince < 60) {
            $memfor = $memsince . "Seconds";
        }else if($memsince < 3600 && $memsince > 60){
            $memfor = floor($memsince / 60) . " Minutes";
        }else if($memsince < 86400 && $memsince > 60){
            $memfor = floor($memsince / 3600) . " Hours";
        }else if($memsince < 604800 && $memsince > 3600){
            $memfor = floor($memsince / 86400) . " Days";
        }else if($memsince < 2592000 && $memsince > 86400){
            $memfor = floor($memsince / 604800) . " Weeks";
        }else if($memsince > 604800){
            $memfor = floor($memsince / 2592000) . " Months";
        }
        return (string) $memfor;
    }

    /* Extra Tools/Functions */

    /* Check if valid E-Mail */
    public function validEmail($email = ""){
        return filter_var($email, FILTER_VALIDATE_EMAIL);
    }

    /* Get the current page URL */
    public function curPageURL() {
        $pageURL = 'http';
        if(isset($_SERVER["HTTPS"]) && $_SERVER["HTTPS"] == "on"){$pageURL .= "s";}
        $pageURL .= "://";
        if($_SERVER["SERVER_PORT"] != "80") {
            $pageURL .= $_SERVER["SERVER_NAME"].":".$_SERVER["SERVER_PORT"].$_SERVER["REQUEST_URI"];
        }else{
            $pageURL .= $_SERVER["SERVER_NAME"].$_SERVER["REQUEST_URI"];
        }
        return $pageURL;
    }

    /* Generate a Random String */
    public function rand_string($length) {
        $str="";
        $chars = "subinsblogabcdefghijklmanopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        $size = strlen($chars);
        for($i = 0;$i < $length;$i++) {
            $str .= $chars[rand(0,$size-1)];
        }
        return $str;
    }

    /* Get the current page path */
    public function curPage(){
        $parts = parse_url($this->curPageURL());
        return $parts["path"];
    }

    /* Do a redirect */
    public function redirect($url, $status=302){
        header("Location: $url", true, $status);
    }

    /* Any mails need to be snt by logSys goes to here. */
    public function sendMail($email, $subject, $body){
        mail($email, $subject, $body);  /* Change this to something else if you don't like PHP's mail() */
    }
    /* End Extra Tools/Functions */
}
?>

For signup / login / reset password

Questions:

  1. Is this class secure against all kinds of attacks (XSS, CSRF, SQL injection, session hijacking, cookie attacks, ...)?

    I just want an exact thing which is simple and secure to use, but I don't know if I can trust this one.

  2. I also saw something weird: 2 people can be logged in the same account and use the account at the same time (I can login with two different browser at the same time and neither logs out). Is this a security issue? What is this called and should it be fixed?

  3. Is there any better all-in-one class I can use (free or commercial is not important)? I mean something exactly like this but completely secure and reliable.

\$\endgroup\$
6
  • \$\begingroup\$ Nothing is ever immune (nothing to do with it being PHP) \$\endgroup\$ Commented Jan 26, 2015 at 16:57
  • 1
    \$\begingroup\$ @Vogel612 What indication do you see that the posted code is broken? \$\endgroup\$ Commented Jan 26, 2015 at 17:00
  • \$\begingroup\$ @200_success Read through 2. "How do I fix this?" on a related note, I already removed a question asking for PHP-coders to hire. \$\endgroup\$
    – Vogel612
    Commented Jan 26, 2015 at 17:01
  • \$\begingroup\$ @Vogel612 Is it a security issue? \$\endgroup\$ Commented Jan 26, 2015 at 17:02
  • 6
    \$\begingroup\$ I think number two is fine - I'd be pretty ticked if I got logged out while trying to use two devices at once. \$\endgroup\$
    – user34073
    Commented Jan 26, 2015 at 17:02

2 Answers 2

1
\$\begingroup\$

Just from a quick look at your code, I found a couple of issues. I didn't look at it in-depth, so there may be more.

Security

if(!isset($block) && ($saltedPass == $us_pass || $password == "")){:

My password can either be correct or empty to login? That does not seem right.

hash('sha256'

Simple sha256 is not good enough, use bcrypt (this also has the advantage that it manages salts for you and that it uses a timing safe string compare).

$this->dbh->prepare("INSERT INTO `{$this->dbtable}` (`username`, `password`, `password_salt`, $columns) VALUES(:username, :password, :passwordSalt, :$colVals)");

This is open to SQL injection for any additional values, either via $columns, but also via $colVals. You have the same problems in other functions such as updateUser.

$html='<form action="'.$_SERVER['PHP_SELF'].'" method="POST">'; "<input type='hidden' name='token' value='{$_GET['resetPassToken']}'/>";

This is both open to reflected XSS (You are using PHP_SELF in other places as well).

header("Location: $url", true, $status);

Always die after a redirect as clients do not have to follow them, meaning that the code below a redirect will still be executed.

mail($email, $subject, $body);

This is probably open to email injection.

ini_set("display_errors", "on");

Displaying errors is not a good idea. It may provide information for an attacker, and it is not really helpful for legitimate users.

Your cookies should be set as httpOnly.

Also, I did not see any CSRF protection. Did I miss it? If not, you should add it, at least to the login function (see here for an explanation).

Misc

  • Your code is too deeply nested. Especially in the function changePassword. Use early returns to reduce this a bit.
  • Some of your names could be better, for example remCook (don't shorten variable names).
\$\endgroup\$
-2
\$\begingroup\$

While it's not exactly what you're asking here, I see one significant problem already in the way you're asking this:

When releasing security related code for review never ever use production values and try to keep the actual site name etc. confidental.

private $company      = "http://<...>.com"; // Company for name for including in emails

This line alone will show others that this code might be in use on that domain. So in case there are obvious flaws in your code (like code injection vulnerabilities), people might try to abuse those rather than revealing them to you, even if it's "just for fun" for them.

\$\endgroup\$
1
  • \$\begingroup\$ This should have been a comment, and an edit (which you did do) - as an answer this amounts to no more than promoting FUD. \$\endgroup\$
    – AD7six
    Commented Nov 9, 2015 at 13:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.