User auth class and security Just curious if my authentication is secure enough, really. Also wondering if I should ditch the secret variable and just use password everywhere instead.

Note: the method logic must remain seperated because the same User object will have CRUD methods added at a later date.

The table structure:

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `username` varchar(255) NOT NULL,
  `password` varchar(255) NOT NULL,
  `secret` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=latin1 AUTO_INCREMENT=2 ;


The class:

class User {
    public $db;
    public $id;
    public $username;
    public $password;
    public $secret;
    public $signed_in = false;

    function __construct ($db) {
        $this-&gt;db = $db;
    }

    function redirect ($url) {
        header('Location: '.$url);
        die();
    }

    function exists () {
        $sql = "select * from `users` where `username`=:username";
        $stm = $this-&gt;db-&gt;prepare($sql);
        $stm-&gt;bindParam(':username', $_POST['username']);
        $stm-&gt;execute();
        $res = $stm-&gt;fetch();

        if (!empty($res['password'])) {
            if (password_verify($_POST['password'], $res['password'])) {
                $this-&gt;id = $res['id'];
                $this-&gt;username = $res['username'];
                return true;
            }
        }

        return false;
    }

    function signIn () {
        $this-&gt;secret = password_hash($_POST['password'], PASSWORD_DEFAULT);

        if ($_POST['remember']) {
            setcookie('username', $this-&gt;username, time() + 31556926, '/');
            setcookie('secret', $this-&gt;secret, time() + 31556926, '/');
        }       
        $_SESSION['username'] = $this-&gt;username;
        $_SESSION['secret'] = $this-&gt;secret;

        $sql = "update `users` set `secret`=:secret where `id`=:id";
        $stm = $this-&gt;db-&gt;prepare($sql);
        $stm-&gt;bindParam(':secret', $this-&gt;secret);
        $stm-&gt;bindParam(':id', $this-&gt;id);
        $stm-&gt;execute();
    }

    function signedIn () {
        if (!empty($_COOKIE['username'])) {
            $this-&gt;username = $_COOKIE['username'];
            $this-&gt;secret = $_COOKIE['secret'];
        }
        else if (!empty($_SESSION['username'])) {
            $this-&gt;username = $_SESSION['username'];
            $this-&gt;secret = $_SESSION['secret'];
        }

        $sql = "select * from `users` where `username`=:username and `secret`=:secret";
        $stm = $this-&gt;db-&gt;prepare($sql);
        $stm-&gt;bindParam(':username', $this-&gt;username);
        $stm-&gt;bindParam(':secret', $this-&gt;secret);
        $stm-&gt;execute();
        $res = $stm-&gt;fetch();

        if ($res) {
            array_walk_recursive($res, 'sanitize');
            foreach ($res as $k =&gt; $v) {
                if (property_exists($this, $k)) {
                    $this-&gt;$k = $v;
                }
            }
            $this-&gt;signed_in = true;
        }
    }
}


How the class is used at the top of all pages in the app:

$user = new User($db); // create user object, $db is a PDO object
$user-&gt;signedIn(); // determine if they're signed in, populate $user-&gt;signed_in boolean


Signing the user in via a form:

if (isset($_POST['username'])) {
    if ($user-&gt;exists()) {
        $user-&gt;signIn();
        $user-&gt;redirect('dashboard.php');
    }
}


Any feedback is greatly appreciated. Like I said my primary concern here is security.
Don't store passwords on the client side. If your database leak, no one can stop the attacker from sending directly the hash instead of the password. In this case the attacker don't need to know the password at all.
You really want a method redirect in your User class? Think about SRP.
Your User class is half Model and half DAO. And you don't want that. A model full of query SQL isn't a good model. A data access object handles this separation between SQL and Model.