I'm wondering what is happenning when a user logs in a website with or without checking a "stay logged in" checkbox.
From what I understand start_session creates a variable on the server and stores the session id on the client's browser in a cookie, destroyed when closing the said browser.
Following that reasoning, I guess that checking the "stay logged in" checkbox pushes back the expiration date by N seconds, which would be achieved by setting:
setcookie(session_name(), session_id(), time()+N);
In that case, I see no need to use cookies, at least for the logging process.
Am I right or awfully wrong? :)
There are a couple of typical ways a "stay logged in" box might be handled...
You could set the user's info in a persistent cookie, and look for that cookie.
You could create some unique ID (it better be a big one...like a GUID or a hash), store it in a persistent cookie, and let that serve as auth info.
Note that most solutions don't involve the user actually staying logged in; they just make it so that the user doesn't see another password prompt. Keeping the session alive and storing the session ID in a persistent cookie is technically possible, but for a site with a lot of users, that'd be quite a bit of extra space and load on the server.
The way I have written an option like that is to create a token and store it in the database along with the user ID. I then give that token to the browser as a cookie. Anytime a page request is done, I check to see first if the user has an active session, then if they have this token cookie. If they have a token cookie, I look into the database to see if it is valid and if so create a session with that user ID.
I'm sure this is an insecure, easily breached method, however.
Related
I'm currently working on a little instant messaging project. So far everything has been going pretty well.
The only problem is security. When someone logs in, 2 cookies are set.
1) Name: loggedin; Value: {username}
2) Name: mvc; Value: {userSecretKey} <-- pretty useless
These are the cookies that I use so I can setup the next page. However, I believe there is a far better way to do this. And no, I don't want to use sessions because I have a "remember me" feature.
Someone could just set the cookies themselves and "sign in" without actually signing in.
What would be a better way to set this up? Maybe some sort of changing key?
I would suggest using PHP Sessions alongside cookies that are purely used for the remember me feature. You could set it up like this:
User logs in
You store the user IP and Useragent in the session
If remember me is enabled, create a new database entry with the user id, an unique random id + IP & useragent of user, then add a cookie that references the unique random ID.
Everytime you access the session, check that the request IP and Useragent match with the ones originally set in the session when the person logged in.
When the user returns after they close their browser, where only the remember me cookie is left, compare the request IP and Useragent to the one in the Database
If they match, log them back in automatically.
Users have fun.
Cheers!
You can still use PHP Sessions even with a 'Remember Me' function. You just need to set the cookie with the userid or username, and then, if they aren't logged in and the cookie exists, read their info from the cookie and log them in.
Have your logic that checks if the user is logged in check for an active session for logged in user. If it doesn't exist, redirect user to log in. In your login logic, check to see if the 'remember me' cookie is set. If it is, log the user in using the cookie. If the cookie doesn't exist, present a log in form.
for the security bit, you can use the secret key that get's reset when you log the user in. Would it be hijackable, yes, but if you keep changing the secret key/token the window for hijacking should be small.
When a user logs into my site it creates 2 cookies, one with a session ID (that relates to the user ID on the backend) and a remember me cookie that lasts for 3 months.
The remember me cookie is constructed as:
userid:timeout:hash
Where the hash is a HMAC SHA256 hash of userid:timeout to prevent tampering.
If the session ID does not exist (user closes their browser and opens it again so the cookie is gone, or the session ID does not exist in memcached) it looks at the remember cookie and re-generates a new session cookie, providing it has not timed out and the hash is correct.
However I don't see the point of having a session cookie at all, as the session ID just points to a user ID in the backend. I can use the remember me cookie instead to retrieve the current user.
So I am thinking of scrapping the session cookie completely, and would be interested in hearing some thoughts on this. Does this approach sound relatively secure? Could I make it any better?
Thanks in advance!
Yes, it is indeed secure enough for most cases, but why including user specific data in the cookie when you can avoid it? Also, there's a small disadvantage with this:
What happens if an user manages to steal a cookie from another user, you'd have to change the whole way the cookies are generated or that user will always have access, therefore resetting everyone's cookies. Imagine now that it's your cookie that gets stolen...
This is my solution for that: create another row in the user table called 'userhash'. When an user logs in, you generate a random hash without taking any of his input, just random, and store it both in the table and in the cookie. Then you only have to store userhash:timeout in the cookie. You check that against the database to see if it exists, if it does, that's your user. When the user logs out, the cookie and the row in the database gets deleted. For obvious reasons, you'd have to check that the cookie exists before comparing (there will be many empty).
Note: This method would only allow one registered cookie at once, so no laptop + desktop. This is good, since stealing is made more difficult as it only lasts as long as the real user doesn't log in, and bad because it only allows 1 computer. But you see the idea and how you could use this method but having several computers logged in... facebook-like.
PD, it'd be nice if you said how secure your app must be actually...
PD2, in case you haven't think about it yet, there are other more serious security concerns (SSL to say one).
I am trying to understand security when it comes to session cookies in php. I've been reading a lot about it, but I still lack the specifics. I need the basics, someone to show examples.
For example: Do I place session_regenerate_id() before every session cookie? What more shall I think about. I am asking about specifics in code - examples if possible.
Thank you very much.
I am using 4 session cookies after logging in.
SESSION "site_logged_in" = true
SESSION "site_user_nr" = the number of the user to access user_table_nr
SESSION "site_user_id" = the user's id to use when changing data in tables
SESSION "site_user_name" = the name of the user to display on page
When I check if the user has access, I check if all 4 cookies are set, and if site_logged_in is set to true.
Are there better ways? Do I have the completely wrong idea about this? Can users easily be hacked?
In fact you need to have only one session in your website. When you call session_start() session is being created on server and user automatically gets session cookie. Think like session is a some sort of container that placed on the server, you can put whatever you want in that container. However session cookie is just a key to access that container on the server.
It means that you can safely put some data in the $_SESSION and only the user that have cookie with matching session id can read it.
About users being hacked. Yes they can be hacked as long as you don't use HTTPS connection, because cookies and all other data is being transferred in clear text, so if someone intercept users cookie he can access the data stored in the session.
Always use a security token for logging users. This security token could be generated by using crypt(). After logging users in, change the security token periodically until they log out. Also keep the server backup of all the session variables including the security token (in a database). This would also help you to track user login history.
One more personal suggestion: Never use any data from the database as session variables without encrypting it with any of the hashing functions or functions like crypt().
The session information is stored server-side. What you should check is that they're logged in, and that they exists/can log in (in case of deletions/bans).
As you're checking they exist/can log in, you can pull the other information from the database such as name, nr and so on. All you really need is a key called 'logged_in_user' or something that stores the ID of the logged in user. As Alex Amiryan said, the cookie can be copied, so you might also want to store the IP address of the last accessing view in the session, so you can try to ensure security.
What is the best way to securely authenticate a user ?
So far I was thinking of:
Generate a random $SALT for each successful login and store $logged = md5($hashed_password.$SALT) into database; delete on logout.
Store $logged into a cookie (If user checked "remember me"). Set $_SESSION['user'] = $logged;
On a visit: Check if $_SESSION['user'] is set; if not, check for cookie, if data doesn't match, redirect to login page.
What are the risks ?
The only issue I can see with your existing framework (which I like otherwise) is that there is the possibility of collision for $logged.
It is not mathematically impossible for two valid user log-ins to result in the same hash. So I would just make sure to start storing the User id or some other unique information in the Cookie as well.
You may also want to keep a timestamp of when the $logged was put in the DB, so that you can run cleaning queries where they are older than x days/weeks.
The first step is a bit overkill, as this is what $_SESSION['foo'] basically does client-side for the lifetime of the session. I'd just store a salted and hashed password for each user to begin with, salting with the date or other pseudo-random factors.
Setting the cookie might prove useless if the user clears their cookies, or the session expires. This will leave the user logged in (according to your database) when in reality they're not.
I'd stick to just $_SESSION['foo'] and cookies and leave the database out of the login process.
First No need of doing
Store $logged into a cookie (If user checked "remember me")
Starting the session should be the first thing you should do place session_start() on top of your index.php (file which gets executed) . This way a cookie name "phpsessid" gets created on user browser by default independent of weather user is logged in or not . value of this cookie is unique by which you can identify the user after he logs in. So you dont need to create any other cookie for this purpose.
In first point you have mentioned It create random SALT string when user logged in and clear it when user log out.
Main problem is you have to check SALT string is exist or not in each redirection of page. So it create heavy traffic in Database server.
Yes this is very useful for checkout user already logged in or not.
But in case of power failure in client machine after log in when Salt string remain in database after long time.
In second point to user authentication in cookie it is not secure. Client can easily show authentication cookie in browser
In third point to store authentication in session it means create session variable on server side and store it in file on server side. It is very secure then store it in cookie.
The best way to authentication is combine point number 1 and 3 which you mention.
You can check user already logged in form other pc or not?
You can easily clear SALT string if session is not exist.
You can easily manage Login in case of pc power failure
One problem I can see - your solution sounds annoying for people who load your site in multiple browsers at the same time.
I'm using login function in my site with session.
This session of mine gets expired after a few minutes irrespective of whether the user has logged out or not.
Now what I want is that the session should only get expired when a user logs out. If a user doesn't log out his account and then comes back after 2-3 days, even then he should appear logged in.
I have found some examples where they have increased the time for a session to expire but I want that it should only expire on the log out event by the user irrespective of the time he took to log out.
How can I do that?
In particular, is this the right way to do so?
session_cache_expire(0);
session_start();
A solution that is often used, in this situation, is to:
have a not-too-long session duration: it will expire if the user is not active (that's just the way it works -- and that's better for your server if you have lots of users)
when user logs in, you set a cookie that contains what is needed for him to be recognized
if he comes back on the site (with the cookie, and without having an active session), you use the informations contained in that cookie to auto-log him in, re-creating the session at the same time.
This way:
you don't have thousands of sessions "active" with no good reason
you keep the standard way sessions work
And you have the advantage of "never being logged out", at least from the user's point of view.
Also note that with "normal" sessions, the cookie containing the session id will be deleted when the user closes his browser -- so, he will be disconnected, no matter how long the session's lifetime is.
With the solution I propose, you are the one who sets up how long the cookie should remain on the user's computer ;-)
It means, though, that when a user manually logs-out, you have to delete both his session and the cookie, of course -- so he's not immediatly re-auto-logged-in.
Of course, you have to be careful about what you set in the cookie: a cookie is not quite secure, so don't store a password in it, for instance ;-)
Actually, this way of doing things is how the "remember me" feature often works; except, here, your users will not have to check a checkbox to activate "remember me" ;-)
If you don't have the time to develop that kind of stuff, a pretty quick and dirty way is to use some Ajax request on all your pages, that will just "ping" a PHP page on the server -- this will keep the session active (but it's not quite a good way of doing things: you'll still have LOTS of sessions on the server, you'll have lots of useless requests... and it will only work as long as the user doesn't close his browser).
You can't do that with the PHP internal session handling alone. PHP will always send out the session id in a session-cookie which will expire when the user closes his browser. To achieve some sort of auto-login you'll need some accompanying code that sets a longer-lasting cookie on the user's browser and handles the recognition of these cookies and the mapping between the cookies value and the respective user account.
Please note that this greatly affects security issues so you'll have to take care of a lot of things. Please read the following on how a possible auto-login feature could be working:
Persistent Login Cookie Best Practice
Improved Persistent Login Cookie Best Practice
Do you remove your cookies while testing? Are cookies enabled? Do you destory the session somewhere in your code?
Also, see my answer to another post: Quick question about sessions in PHP which explains how to stay signed in. Just don't do a cronjob/sheduled task if you want the user to stay logged in forever.