I'm making a website where some users can log in. I have my code create a simple cookie. Earlier my code was working and creating a cookie and allowing users to sign in. However, after I created a log out button and used it, I couldn't seem to create a cookie again (my website doesn't recognize a cookie and no cookie shows up in chrome when I check). I've already looked at all the other threads about creating a cookie and not being able to create a cookie, but I can't figure out what is wrong.
Here is my code to create a cookie:
$userStuff = array('name' => $username,'password' => $password);
$date_of_expiry = time() + 60 * 60 * 24 * 1 ;
setcookie( "user", $userStuff, $date_of_expiry, "/" ) ;
I know that the security is extremely lax and that I shouldn't store the password and such directly in a cookie, but I want to work on other things first. This code is before any html.
Here is my code where I changed the expiration date of the cookie to log out:
setcookie('user', $userStuff, time() - 3600, '/');
how are you?
If you want to delete a cookie, you should pass a date in the past, for example:
setcookie('user', $userStaff, time() - 3600, '/');
Regards.
I know this is a bit aside the point, but why not use $_SESSION? It stores a cookie with a session token in your client's browser (when you run session_start) and most of the data is stored server side which is far more secure. For user auth data and tokens this is probably a better choice.
Example:
//First thing init the session
session_start();
$_SESSION['username'] = $username;
$_SESSION['password'] = $password;
//Or retreive the data...
$username = $_SESSION['username'];
//Later when you want to log out just destroy the session:
session_destroy();
I found the error. Apparently, you either cannot use arrays in cookies, or it just wouldn't let me use an array in my cookie this time.
Related
I have a custom written PHP application. Build 15 years ago. Working perfectly fine until recently when users reported they are being logged out even while they are actively using the application.
We use PHP sessions to manage users. The session expiry is set to 12 hours of inactivity. I reproduced the issue of being logged out. There is no pattern. at times I was logged out after 30 mins, at times 2 hours, at times 40 mins and so on. I captured the PHP session cookie and checked that the corresponding PHP session file existed in the tmp directory on the server. The session file was there on the server even when the application got me logged out and it was not even 2 hours (expiry set for 12 hours).
If I print the $_SESSION, this issue does not appear as much. Reproduced the issue in Chrome and Firefox. I have session_start and session_destroy only in logout service.
Any leads what could be causing this?
I faced same problem a few times. Workaround: use a "remember me" cookie for auto login.
Here's a recipe:
Whenever user logins successfully run this:
// remember me for a year every login
$login_string = hash('sha512', $user_id . $_SERVER['HTTP_USER_AGENT'] . time());
Project::update_table_record('users', $user_id, ["remember_me" => $login_string]);
$cookie_name = COOKIE_REMEMBER_ME;
$cookie_value = $login_string;
setcookie($cookie_name, $cookie_value, time() + (86400 * 365), "/"); // 365 day example
Whenever user chooses to logout, give him the option:
setcookie(COOKIE_REMEMBER_ME, "", time() - 3600, "/");
Otherwise, if no session then re-login if cookie is valid.
// auto login / remember me!
if (!LiveUser::get_id()) {
if (isset($_COOKIE[COOKIE_REMEMBER_ME])) {
$user_string = $_COOKIE[COOKIE_REMEMBER_ME];
$user_id = Project::get_value('users', ['remember_me' => $user_string], 'id');
if ($user_id) {
Project::do_login($user_id);
}
}
}
I want to set a cookie if Username is entered and also want the previous cookie to get deleted. I am able to unset the previous cookie but new cookie is not working for me. It showing blank.
if(!empty($User_Name))
{
unset($_COOKIE['username']);
setcookie('username', $User_Name, time()+31536000);
echo $_COOKIE['username']; // blank
}
Any help would be nice.
In my opinion there is no need to unset the cookie. Because, when you set the cookie it will override the existing cookie ( if it exists ) or create a new one ( if it doesn't exist )
From the PHP Docs..
Cookies will not become visible until the next loading of a page that
the cookie should be visible for. To test if a cookie was successfully
set, check for the cookie on a next loading page before the cookie
expires.
Found that if the path is empty it applies only to the current path, if you specify "/" applies to all paths.
so / did the trick.
setcookie('username', $User_Name, time() + (86400 * 7), "/");
This is my code to control authentication on a website. I'm not sure if my logic is correct. If the username and password are correct the following happen:
if(session_start())
{
session_regenerate_id(true);//without this the session ID will always be the same
$_SESSION['loggedInUser'] = $uName;
echo 'You are now logged in';
}
else echo 'Right password/username but session failed to start';
Subsequent pages check to see if the user is logged in by
session_start();
if(isset($_SESSION['loggedInUser'])
{
//rest of page
}
else echo 'you must log in';
When logging out I have
session_start();//if I don't have this the next line produces an error
session_unset();//destroys session variables
session_destroy();//ends session
I red not to call session_start() on logout but if I don't have it there I get the message Trying to destroy uninitialized session. How can I fix this?
Is it recommend or not to create a finger print based on the IP address and user agent? I red it's bad because multiple computers can share the same IP address if they are in, for example a computer lab, and all the traffic goes through a proxy and the same computer could change it's IP address if it's dynamic. On the other hand, how often does this happen? It may be worth the few blocked valid uses to prevent all session hijacking.
Even if you could recommend reputable articles I should read to learn about this topic that would be great, thanks.
5/6 answers have votes less than 0 :( Could down voters comment so I know what to look out for?
First of all you should read the Mozilla WebAppSec Security Coding Guideline - Session Management and OWASP A3-Broken Authentication and Session Management. You can configure PHP's session handler to meet these requirements.
The first flaw you should prevent is A9-Insufficient Transport Layer Protection. In short you do not want someone to hijack a session using a tool like Firesheep. This attack can be prevented by forcing the browser to only send the session id over https:
session.cookie_secure=1
You can prevent an attacker from obtaining the session id using XSS by setting the httponly flag:
session.cookie_httponly=1
You always want to use a cookie to store your session id. If the session id can be passed using a GET or POST variable then an attacker could use Session Fixation attack to hijack a session. Another way of thinking about this attack is that you don't want an attacker to create a session for another user:
session.use_cookies=1
session.use_only_cookies=1
Next you want to make sure you have atleast 128 bits of entropy from a CSPRNG. Under *nix systems you can use /dev/urandom:
session.entropy_file="/dev/urandom"
session.entropy_length=16
The session handler isn't everything. You still need to worry about Cross-Site Request Forgery attacks (aka CSRF or "Session Riding"), and Cross-Site Scripting (XSS). XSS can be used to defeat CSRF protection (even with http_only cookies!). Clickjacking can also be used by an attacker to perform unauthorized actions.
After you set these configuration options, just call session_start(). As for destroying the session call session_destroy() when the user logs out, its that simple!
To securely destroy a session I would use the following code:
session_start();
// Unset all session values
$_SESSION = array();
// get session parameters
$params = session_get_cookie_params();
// Delete the actual cookie.
setcookie(session_name(), '', time() - 42000, $params["path"], $params["domain"], $params["secure"], $params["httponly"]);
// Destroy session
session_destroy();
In order to destroy a session you need to start it first, as you have found out it doesn't work if you don't include session_start();
The session_regenerate_id(); Function generates a new session id for the user. If used with true (session_regenerate_id(true);) then the old session id is deleted from the server when it generates a new one. The reason behind generating a new session id on every page is that it makes session hijacking much harder (Nearly Impossible?) to perform because of the users constantly changing session id.
(View PHP.net manual on session_regenerate_id();)
When authenticating a user you should always check something like the IP address or Browser, these are constant things sent in the request to the server that do not change in the life time of your session, and if they do then you know something dodgy it happening. I always create two session variable one that stores the user ID so I can query a database for data, and another that stores the users password, IP address and Browser String all in one hash (sha512).
$user_id = $_SESSION['user_id'];
$login_string = $_SESSION['login_string'];
// Query Database and get hashed password
$login_check = hash('sha512', $password.$ip_address.$user_browser);
if($login_check == $login_string) {
// Logged In!!!!
return true;
} else {
// Not logged in
return false;
}
The password is secure even though it is being stored in the session. This is because the password is hashed (Twice in this case) and because the session data is not stored on the users computer (Like cookies), it is stored in a session file.
I wrote an article on wikihow.com about secure login and authentication, is can be found here.
You can just write:
session_start(); // session should be started before it can be used.
You can assign userid of logged in member. For this you can take username and password from user input and check it in your db and return userid. For more security you can have strings for eg. "demo" and "test" just md5 both and mix it with userid in following manner.
$userid=md5("demo").$userid.md5("test");// you can set any string instead of demo and test.
$_SESSION['userid']=$userid;
While using it in other page,
session_start(); // If you are have not started it or included above code file in it.
As you know the strings while using just match it and find the exact userid from it and use it in your code.
For destroying it just use:
session_unset($_SESSION['userid']); // It will only unset the session userid completely.
Make sure that before use of any session you need to start it. In better way you can start the session in one file say init.php and include it every where where you want to use the session
You can first use session_id() to determine whether the user already got a session, if not, then use session_start().
example codes from Lithium framewrok:
/**
* Starts the session.
*
* #return boolean True if session successfully started (or has already been started),
* false otherwise.
*/
protected static function _start() {
if (session_id()) {
return true;
}
...
return session_start();
}
After call _start(), you can safely call session_destroy()
To destroy a session without using "start_session()", first verify whether there is an active session of not like below
$existingSessionId = session_id();
if ($existingSessionId != "")
{
// Initialize the session.
session_start();
// Unset all of the session variables.
$_SESSION = array();
// If it's desired to kill the session, also delete the session cookie.
// Note: This will destroy the session, and not just the session data!
if (ini_get("session.use_cookies")) {
$params = session_get_cookie_params();
setcookie(session_name(), '', time() - 42000,
$params["path"], $params["domain"],
$params["secure"], $params["httponly"]
);
}
// Finally, destroy the session.
session_destroy();
}
else
{
// No Active sessions
}
session_regenerate_id(true), just replace the old session id with the new one but it does not unset the old session id. This needs to be taken care by session_destroy and deleting session cookie.
Browser will send session cookie to server ever session is destroyed. PHP will get this session ID and when you do start_session(), it will use session id sent by browser. If you delete the session cookie, session_start will generate a new session id and you do not need to call session_regenerate_id()
<?php
session_start();
$_SESSION['logged_in'] = false;
setcookie("dsgpassword127", $password, time()-3600); /* expire the cookie */
setcookie("dsgemail127", $email, time()-3600); /* expire the cookie */
session_destroy();
header("location: index.php");
?>
The code above which works very well in Chrome will not remove the cookies in FireFox 14.0.1. I am wondering why this is, if anyone has experienced the same problem or if there is a solution to this conundrum I am in when it comes to expiring these cookies....
According the manual for sesion_destroy():
session_destroy() destroys all of the data associated with the current session. It does not unset any of the global variables associated with the session, or unset the session cookie. ...If a cookie is used to propagate the session id (default behavior), then the session cookie must be deleted. setcookie() may be used for that.
Hard to explain why Chrome is unsetting the cookie, but it's Chrome's behavior that appears to be aberrant, not that of Firefox.
But the presence of an old cookie pointing to a dead session should not be problematic. The server should create a new session - with empty session data - and send back a cookie pointing to the new session.
In fact, saving unencrypted users and passwords on the client is probably ill-advised. Are you sure you need that? Storing that info on the server-side is probably more common, with the client-side only given his the session cookie.
I uninstalled FireFox and reinstalled the latest version which is 15.0. This time when FireFox asked me to remember the password automatically I requested it not do so. Now the browser is reacting normally. I suspect that the same would have been the case also in 14.0.1 in regards to the "Remember password" feature.
Just set the cookie expiration to 1 like so:
setcookie("dsgpassword127", $password, 1); /* expire the cookie */
setcookie("dsgemail127", $email, 1); /* expire the cookie */
Basically the third parameter is the number of seconds since epoch. 1 sets it to 1 second after epoch and so there is not need to worry about time() and all. Check if that helps in firefox.
I have a page (mypage.html) which sets a cookie as follows:
setcookie ("sessionid", md5 (uniqid (rand())));
Now, at the top of an include which displays the site header I have the following:
echo "cookie is ". $_COOKIE['sessionid'];
When I am on mypage.html, which includes the header, the echo command displays the cookie name, as it should...e.g.
cookie is 4d40102ff2d2268d907dd31debc411e2 cookie is 4d40102ff2d2268d907dd31debc411e2
But if I move aeway from the page which set the cookie, all I see is
cookie is
with no name - If I go back to mypage.html it reads it again with no problem. I have no clue how this can happen?? Any ideas?
Set an explicit path for the cookie. The default is the current directory only, so if you navigate to a script in another directory, the cookie won't be sent back by the browser.
// Cookie is valid for all paths ( / ) in the current domain
// This also has an explicit expiry time of 1 hour from the time it's set...
setcookie ("sessionid", md5 (uniqid (rand())), time() + 3600, "/");
It's a little unusual to be setting your own session cookies though, when simply initiating a session handles it for you:
session_start();
// Id is set for you...
echo session_id();