7

There are many instances in my code where quick access to the logged in username and userid is needed. I currently use cookies. This isn't secure.

I thought sessions would be a solution but sessions expire.

Another option, is to store a unique token in a cookie and then match with a stored token in the database, to retrieve logged in user data. This is the most secure solution but the problem i see with this is, there are many times in my code where the logged in username and userid is needed but querying all the time would use up resources unnecessary(is this true?)

What is the solution?

user892134
  • 2,906
  • 13
  • 50
  • 101
  • 3
    Use sessions and increase session expire time . – Dhruvisha Jul 18 '12 at 11:44
  • 2
    I highly recommend you read [The Definitive Guide to Forms-Based Website Authentication](http://stackoverflow.com/questions/549/the-definitive-guide-to-forms-based-website-authentication). – Polynomial Jul 18 '12 at 11:48

3 Answers3

5

I'm going to try to coalesce everything that's been said in the comments into one answer. As such, please show other helpful users some love by upvoting their answers / comments! I'm also going to give a brief overview of how sessions work, to make the answer useful to a wider audience.

When a user logs into a website, a session is created to identify them. Sessions are handled in PHP by creating a session ID, then associating that ID with a variable store on the server side, which is accessed in PHP scripts using the $_SESSION superglobal. The session ID is stored in a cookie on the client-side, and identifies their session.

In order to remain secure, the session ID must be unique, random and secret. If an attacker guesses your session ID, they can create a cookie on their own computer using that same ID, and take over your session. They'd be logged in as you! This is obviously bad, so PHP uses a strong random number generator to create those session IDs. In order to make things more secure, you can enable SSL site-wide and inform the browser to only ever send the cookie over SSL, using the HTTPS-only flag. This might be overkill for your site, though.

In order to prevent leaked session IDs from being useful forever, or bad guys sneaking into your room after you've gone out to the shop, sessions use timeouts. It is best to have them expire after a reasonably short time - between 10 and 60 minutes depending on your security requirements. You can reset the timeout every time you view the page, so an active user doesn't get logged out.

In order to allow the user to be remembered (i.e. the "remember me" checkbox), you need to provide a cookie that works as an authentication token. Keep in mind that this token is, for all intents and purposes, the same as having your password. This means that if the bad guy steals the cookie, they can log into your account. In order to make this option safe, we can use a one-time token. These tokens should be single-use, random, long and secret. Treat them as if they were passwords!

Here's how to implement them:

  1. Generate a random token. Use /dev/urandom if you can, otherwise you need several hundred values from mt_rand to get something "random" enough, then hash the resulting string with SHA1 to produce the token.
  2. Use a strong password hashing algorithm (e.g. PBKDF2 or bcrypt) to create a hash of the token. Do not use SHA1 or MD5 for this purpose - they are NOT designed for hashing passwords!
  3. Insert the hash into a database table, along with the ID of the user it belongs to and the date it was created.
  4. Set the token in a cookie on the user's side.
  5. When the user visits the site, is not logged in, and a login token cookie is detected, hash the token value from the cookie using the same algorithm you used in step 2, and look it up in the database. If it matches an entry, log the user in as that ID.
  6. Delete the entry from the database and issue a new one (back to step 1).

You should also run a script that looks for very old session tokens (e.g. 3 months or more) and delete them. This will require the user to log in again when they come back after a long period of inactivity.

For a longer explanation of this, and many more important bits of information about secure web form login systems, read The Definitive Guide to Forms-Based Website Authentication and take a look at the OWASP project.

Community
  • 1
  • 1
Polynomial
  • 25,567
  • 8
  • 75
  • 106
3

If it is not needed on the client, make sure it does not end up there.

Since userId's are specific to a logged in user and not a specific computer, a cookie does not seem like the way to go.

Basic authentication in PHP is usually done with sessions, so you could just as well add the userId to the session.

If the session times are too short, increase the session time.

Timothy Groote
  • 8,303
  • 25
  • 52
  • 1
    Ok thanks, last questions. What is the max session time i can assign? I don't want the user to keep on having to resign in. Also what if the session expires(even with increased session time). Should i do if the session expires then fetch the username/userid from database and set session again? – user892134 Jul 18 '12 at 11:56
  • 1
    If you don't want the user to have to keep signing in, use an always-remember-me system based on one-time tokens. Keep the session timeout relatively short - somewhere between 10 and 60 minutes depending on your security requriements. See *"PART II: How To Remain Logged In - The Infamous "Remember Me" Checkbox"* of [The Definitive Guide to Forms-Based Website Authentication](http://stackoverflow.com/questions/549/the-definitive-guide-to-forms-based-website-authentication) for details on how to securely handle such a feature. – Polynomial Jul 18 '12 at 11:57
  • If it is allowed, you could overwrite the php default settings with the following line : `ini_set(‘session.gc_maxlifetime’, ’28800′); // sets the session time to 4 hours` or just edit the php.ini file (where it actually should be done). If the session expires, kick the user back to the login screen. – Timothy Groote Jul 18 '12 at 11:58
-4

I store such information in a database and on startup create a user object in my global object-registry. The user object holds information like user-name or e-mail and allows for changes of those infos. The login-status itself is stored in the session and also in a cookie.

feeela
  • 26,359
  • 6
  • 56
  • 68
  • @Polynomial What is insecure and how? To store infos in a database or to use cookies to identify an user? How else would you recognize an user, when he comes back to your site? – feeela Jul 18 '12 at 11:49
  • By having them log in again. Keeping any kind of session identifier clientside is a security risk. Such cookies could theoretically be stolen and used to hijack someone's session – Timothy Groote Jul 18 '12 at 11:50
  • Using cookies to identify the user is incredibly bad from a security point of view. You need to use a session cookie to identify the session, using a strong unique ID algorithm to generate the session ID. The session cookie must be secure (i.e. using the HTTPS-only flag). You should never store user information in a cookie. They can be edited or stolen very easily. – Polynomial Jul 18 '12 at 11:50
  • @Polynomial : even that is still more risky than just having users log in anew. – Timothy Groote Jul 18 '12 at 11:52
  • 1
    @TimothyGroote Sure, but I'm talking about in general for session management. You need session IDs to manage... well, sessions! The user should have to log in again after the session expires. If you absolutely have to use one, always-remember-me systems should be based on one-time tokens, and should also require the HTTPS-only flag. – Polynomial Jul 18 '12 at 11:53
  • 1
    Agreed. :) though PHP can handle a lot of those things for you, and there is no immediate need to interfere with its own session management. – Timothy Groote Jul 18 '12 at 11:54
  • There's no need to interfere with it, outside of hardening. Setting the session cookie path and HTTPS-only flag isn't part of PHP's standard session management. – Polynomial Jul 18 '12 at 11:55
  • @Polynomial That's exactly what I've done. The cookie I meant is the session cookie, which is created through PHP. Maybe my answer was bit unclear, but there are no user-information inside the cookie itself. – feeela Jul 18 '12 at 11:56
  • @TimothyGroote "By having them log in again." The usability goal on most websites is to let the user stay logged in throughout many browser session. I can't remember any website, where the user get logged out automatically after closing the browser. – feeela Jul 18 '12 at 11:59
  • 1
    @feeela That's done through one-time authentication tokens in cookies, not extending the session cookie length. See my comment on Timothy's answer. – Polynomial Jul 18 '12 at 12:00
  • There are a lot of things to this, too much to explain in a few minutes. Make sure to read up on what @Polynomial says, he knows what he's talking about, and his links are really helpful. – Timothy Groote Jul 18 '12 at 12:02
  • I don't get it. Maybe my English is too bad. Maybe me and millions of software developer have done insecure authentications in the last ten years. TYPO3, Wordpress, Plone, etc. – they all use cookies to identify the users and let them stay logged in by increasing the cookie duration. Is there any buzzword I should search for or does anyone know a tutorial to get a basic understanding of what @Polynomial means? Timothy, which links? – feeela Jul 18 '12 at 12:10
  • `The Definitive Guide to Forms-Based Website Authentication` (second comment, question post) – Timothy Groote Jul 18 '12 at 12:18
  • 1
    Also, yes ; there are a *lot* of frameworks and applications with insecure authentication – Timothy Groote Jul 18 '12 at 12:19
  • A ridiculous number. Most of them are still using concatenated queries instead of parameterised statements, too. – Polynomial Jul 18 '12 at 12:25