views:

70

answers:

2

I've been told that it is insecure to store things such as passwords, usernames, and user ID's in cookies, and that instead you should store a sessionID in a cookie. Here's where I get lost.

My objective is to have a basic 'remember me' feature. Normally I would store user login information in a cookie, but as this is unsafe, I'm wondering what the alternative is. I understand that each time I create a session it creates a cookie which creates a unique ID, but expires when I close my browser. So how do I get access to this session information after the browser has closed?

All help is appreciated.

+2  A: 

This could be a fairly steep learning curve. Have you considered using a pre-existing CMS or other solution for what you're wanting to achieve, or even a framework that might include this functionality?

For a 'remember me' feature you can send out cookies containing the user ID and a hash of that user's hashed password hashed again with some known, but secret, token. That solution doesn't allow you to remotely expire someone's login, however, without resetting someone's password.

Another approach therefore is to generate a unique token for that person's login and have another database table relating that unique token to a particular user and expiry date.

thomasrutter
definitely the latter approach...
Mitch Wheat
But wouldn't using a token be just as vulnerable as storing a password or userID?
WillyG
And regarding the first part of your response, I have considered using templates, but there are reasons I don't. Mainly, I enjoy doing it myself and I enjoy learning how to do it. In my mind, I won't learn how to so it unless I do it myself. (And by doing it myself I mean learning how to do it on the web, or from the fine folks here at SO)
WillyG
"wouldn't using a token be just as vulnerable as storing a password" - in a way yes, but it's a necessary evil with persistent logins that you're essentially giving the client an alternative way to log in without a password. The benefit though is that the user's password itself isn't revealed, just a token that can only be used at this site, and you'd still verify the user's password when they initiate any high-risk activities such as updating their email or password, etc. You also have the option to invalidate a token after a specific amount of time without requiring a password change, etc.
thomasrutter
And good for you for wanting to learn how it all works yourself ;) That's a good enough reason to do something yourself in my book - if you have the time and desire to do so.
thomasrutter
+1  A: 

Possibly the best approach, as has been suggested and what most third-party apps do, is to create a "user_sessions" database table with the following fields:

session_id (var_char)
user_id (int)
ip_address (var_char)
last_logged_in (unix timestamp)

Then use a cookie to store an md5 hash of whatever you like, possibly:

md5($username.$ip); //since md5 has a lot of reverse look ups now you should use a number of fields to validate. You could use a different crypto function to make it more difficult to crack, but md5 is the simplest version available in all php versions.

EDIT: You will then compare the stored hash from the cookie with the database session_id to see if they have already logged in. The reason to combine a couple of fields in the md5 function is to create a less "guessable" hashing format. It makes it less likely someone will be able to edit a cookie and login as someone else.

This could be done for all users (this way you can track who is online) and just set a "persistant" login variable in the cookie. eg.

p_login=true || p_login=false

That way you'll know whether to auto login or force login.

note: You may be able to look at http://www.openwall.com/articles/PHP-Users-Passwords for a different way to hash passwords, session_ids and users.

Josh Stuart
Thanks for this! Couple questions:Is the sessionID the same thing that is stored in the cookie (`md5($username.ip);`) ? //Based on your example, the IP address seems to be used for authentication, so if their IP address changes (proxies) they would have to log in again, correct? (not a problem, just curious.) //Also, what exactly is the purpose of the last_logged_in field? (again, just curious?)
WillyG
The ip address is just something unique to hash against. It is more likely for a user to realize you are just hashing a username. Then they could hack a cookie and login as anyone. If it is md5($username.$ip) it is more difficult to work out what the hash will be.It wouldn't matter if the IP changes as it is stored in the cookie as an md5 hash. So you just check if a session exists in the DB with session_id = 'md5($username.$id)'. if not create it. if it does update with the new IP address and hash.Storing last logged in time and ip is just for security. If unauthorized access u can check.
Josh Stuart
update my answer to clarify a bit more.
Josh Stuart
Ok, so the IP address is just kind of like a salt, except it's unique to each user. And each time they log in with a valid session_id, I would update with a new session_ID, for security purposes, I assume. Sounds good! Thanks for your help!
WillyG
I have one more question, once I've successfully authenticated the user, it's safe to use the built-in $_SESSION variable to store a userID, right?
WillyG
Yes that should be fine, provided you dont store any sensitive data (passwords, credit cards nos. etc) in them. This site: http://articles.sitepoint.com/article/php-security-blunders, has a small summary about $_SESSION and some considerations.
Josh Stuart
Also just going back to password, or in your case "session_id" token, hashing you may want to read http://phpsec.org/articles/2005/password-hashing.html . It has a nice little function to make the hashes harder to reproduce and more unique :D
Josh Stuart