Secure Persistent Logins on multiple computers

I want allow my users to have (relatively) secure persistent logins on multiple computers.

Here’s the strategy I have come up with so far to achieve this, which is based off of this:
(http://jaspan.com/improved_persistent_login_cookie_best_practice)
The problem with it is it seems designed for a single machine, rather than multiple. People will want to log in from phones and more, which isn’t accommodated for in this article. (Or perhaps it is, and I am missing it?)

  1. user logs in with “remember me” checked.
  2. a very large random token created and set as the value of a cookie for the user
  3. (user closes browser)
  4. user returns to site, the token is checked and the user is auto logged in. the token is deleted and a new cookie is set containing a new token. (this repeats, so that the token changes on each visit to the site)

So far this, is not much different than what is specified in the article above. However, I am having trouble coming up with a mysqli table design (along with associated php code) that handles this efficiently on multiple machines. Any suggestions for how I should structure my database? I was thinking about storing all of the tokens in a single field, with some sort of delimiter. Any thoughts on how best to achieve this?

I am also open to better recommendations for how to best achieve multiple machine persistent logins in a secure way. (I know persistent logins are not that secure in general, but that doesn’t mean security can’t be helped a bit.)

The problem is, if the token is deleted and you make a new one then the token on another machine would no longer be valid. So that means you must either store multiple tokens for any given user, or you have to use the same token on each machine.

Storing may increase the chances of brute forcing, but then again storing one may also increase the chances of brute forcing.

You could store multiple and then check user agent strings on each one. That way at least if someone did manage to brute force a key, if they weren’t using the same browser it wouldn’t be valid. This seems like your best option. You should salt the token with something user-unique, like their username or user id, email, etc. That way if you store it as md5 or sha1 a rainbow table attack wouldn’t be as feasible.

For a table design, something like this:

CREATE TABLE `autologin` (
  `user_id` int(10) unsigned NOT NULL,
  `token` varchar(40) NOT NULL,
  `ip_address` varchar(40) NOT NULL,
  `user_agent` varchar(255) NOT NULL,
  `time` int(10) unsigned NOT NULL,
  PRIMARY KEY (`user_id`,`token`)
)

When they login, store this data:


// user_id = their user id
// token = sha1($a_salt . uniqid(mt_rand(), true));
// ip_address = $_SERVER['REMOTE_ADDR'];
// user_agent = $_SERVER['HTTP_USER_AGENT'];
// time = time()

Store token in a cookie also. Now when they try to autologin:


$token = $_COOKIE['token'];

// WHERE token='$token' AND user_agent='$_SERVER['HTTP_USER_AGENT']
// JOIN users ON id=user_id

You can optionally check that the IP’s match, and set an expire time as well.

Hope that gets you in the right direction.

I dont understand what you’re trying to accomplish? The article you linked isnt really any more secure than the standard persistant login setup (create cookie with token. Store cookie. use cookie.). It is better able to report attacks, but the number of false-positives rises.
A table of tokens, foreign keyed to a user table, would store multiple tokens for one user.

@scootshah in your autologin table proposal:


CREATE TABLE `autologin` (
  `user_id` int(10) unsigned NOT NULL,
  `token` varchar(40) NOT NULL,
  `ip_address` varchar(40) NOT NULL,
  `user_agent` varchar(255) NOT NULL,
  `time` int(10) unsigned NOT NULL,
  PRIMARY KEY (`user_id`,`token`)
)

Should the key not be a UNIQUE one made of user_id and user_agent?

I’m user 23, I’m logged in from my workstation.

23
IE 9 / Win32

I go outside, I log in from my phone.

23
Firefox 11 / Android

Or have I failed to grasp the point here?

Then anyone can just put a user id and a user agent in the cookie and boom, logged in as that user.

Why would you store the user agent value in a cookie?

You asked if the key should be made from the user_id and the user_agent. Such a key would be easy to spoof by just putting the values in the cookie.

The key needs to be random and unique. When you log in from a different computer or device, you get a new key for that computer/device.

The correct unique on that table is user_id,token.
2 PC’s in the same household, running the same OS and Browser.

IP = same
Agent = same
Token = Different
UserID = Foreign Key relation.

1-N pairing: UserId,Token.