Jump to content

Trying to get the cookie session functioning: "lost upon reopened browser".


oz11

Recommended Posts

Could I see that GD code?

AND - I am trying to verify that the setcookie runs ok and not looking for something being set.  There's a big difference between the two things.

When working with someone on one's code changes it usually works better if you POST the new code so that we can agree on what we've done.  Not show me some garbage from something else.

Edited by ginerjm
Link to comment
Share on other sites

:thumb-up:

<?php
   include '../includes/config.php';
function setRememberMeToken($pdo, $user_id) {
    $token = bin2hex(random_bytes('25'));

    $expirationDate = time() + (86400 * 7); // <-- 7 days later (make sure your comments are accurate)
    setcookie("token", $token, $expirationDate, "/");
    echo $_COOKIE["token"] = $token;
    $test = true;

    $to = date('Y-m-d', $expirationDate);

    $sql = "INSERT INTO `user_token` (`user_id`, `expires`, `tokenHash`) VALUES (?, ?, ?);";
    $stmt= $pdo->prepare($sql);
    $stmt->execute([$user_id, $to, sha1($token)]);

    if (!setcookie("token", $token, $expirationDate, "/"))
    {
        echo "Could not set cookie for $token using $expirationDate - aborting";
        exit();
    }
}
setRememberMeToken($pdo, 1);
echo "<br>";

?>

[test file]

&&

<?php
// https://forums.phpfreaks.com/topic/315262-php-cookies-and-session-data-expiring-at-different-times/
function setRememberMeToken($pdo, $user_id) {
    //$length wasn't a great name and is an unnecessary variable.
    $token = bin2hex(random_bytes('25'));

    $expirationDate = time() + (86400 * 7); // <-- 7 days later (make sure your comments are accurate)
    setcookie("token", $token, $expirationDate, "/");
    //$_COOKIE["token"] = $token;
    $test = true;

    //$_COOKIE['remember'] is unnecessary, just get rid of it
    //--deleted

    //You calculated your expiration timestamp above already, no need to do it again.
    $to = date('Y-m-d', $expirationDate);

    //Assuming token_id is an auto increment column, you can just omit it from the insert.
    $sql = "INSERT INTO `user_token` (`user_id`, `expires`, `tokenHash`) VALUES (?, ?, ?);";
    $stmt= $pdo->prepare($sql);
    $stmt->execute([$user_id, $to, sha1($token)]);
    echo "test----------------";

        if (!setcookie("token", $token, $expirationDate, "/"))
    {
        echo "Could not set cookie for $token using $expirationDate - aborting";
        exit();
    }


}


function getRememberMeCheck($pdo) {
    //I find spacing out your queries makes them easier to read and understand.
    $stmt = $pdo->prepare("
    SELECT users.name, users.user_id
    FROM user_token, users 
    WHERE 
        tokenHash = ? 
        AND expires > NOW()
        AND users.user_id = user_token.user_id
    ");
    $stmt->execute([sha1($_COOKIE["token"])]); 
    $db_query = $stmt->fetch();
    
    //Your token and expiration date are validated as part of the query
    //All you need to do is check if you got a result or not.
    if (!$db_query){
        //If you didn't get a result, either the token is invalid or it has expired.
        //header("location: login.php");
        return false;
    }


    //Otherwise, if you did get a result, the token is valid.
    $_SESSION["loggedin"] = true;
    $_SESSION["username"] = $db_query['name'];
    $_SESSION["the_usr_id"] = $db_query['user_id'];
    $_SESSION["userID"]  = $db_query['user_id']; // ADDED DUE TO DESCRIPTION ("PROB WILL BE OK")
    return true;
}



//This method seems to just be a copy of the method above, why does it exist?
//The only difference is $_SESSION["loggedin"] = true; which you could just do above.
//function setSessionVarables($pdo) {
//...
//}
//--deleted


function isRemembered() {
    //Instead of a separate remember cookie, just check if the token cookie exists.
    //if ($whatever){ return true; } else { return false} can be simplified to just return $whatever
    return isset($_COOKIE['token']);
}
?>

[functions]

 

 

Link to comment
Share on other sites

That is the modified code :confused:. See..

    if (!setcookie("token", $token, $expirationDate, "/"))
    {
        echo "Could not set cookie for $token using $expirationDate - aborting";
        exit();
    }

it's inserted in both files. The test file #1 and also placed in the functions file (#2), for testing purposes as i thought you wanted..?

Edited by oz11
Link to comment
Share on other sites

Both set but no errors when "logging in" aka "setRememberMeToken"...

[whole functions]

<?php

// https://forums.phpfreaks.com/topic/315262-php-cookies-and-session-data-expiring-at-different-times/
function setRememberMeToken($pdo, $user_id) {
    //$length wasn't a great name and is an unnecessary variable.
    $token = bin2hex(random_bytes('25'));

    $expirationDate = time() + (86400 * 7); // <-- 7 days later (make sure your comments are accurate)
    //setcookie("token", $token, $expirationDate, "/");
    setcookie("token", $token, time() + (86400 * 30)); // 86400 = 1 day

    $_COOKIE["token"] = $token;
    $test = true;

    //$_COOKIE['remember'] is unnecessary, just get rid of it
    //--deleted

    //You calculated your expiration timestamp above already, no need to do it again.
    $to = date('Y-m-d', $expirationDate);

    //Assuming token_id is an auto increment column, you can just omit it from the insert.
    $sql = "INSERT INTO `user_token` (`user_id`, `expires`, `tokenHash`) VALUES (?, ?, ?);";
    $stmt= $pdo->prepare($sql);
    $stmt->execute([$user_id, $to, sha1($token)]);
    //echo "test----------------";

        if (!setcookie("token", $token, $expirationDate))
    {
        echo "Could not set cookie for $token using $expirationDate - aborting";
        exit();
    } else {
        echo "Setcookie ran ok";
    }


}


function getRememberMeCheck($pdo) {
    //I find spacing out your queries makes them easier to read and understand.
    $stmt = $pdo->prepare("
    SELECT users.name, users.user_id
    FROM user_token, users 
    WHERE 
        tokenHash = ? 
        AND expires > NOW()
        AND users.user_id = user_token.user_id
    ");
    $stmt->execute([sha1($_COOKIE["token"])]); 
    $db_query = $stmt->fetch();
    
    //Your token and expiration date are validated as part of the query
    //All you need to do is check if you got a result or not.
    if (!$db_query){
        //If you didn't get a result, either the token is invalid or it has expired.
        //header("location: login.php");
        return false;
    }


    //Otherwise, if you did get a result, the token is valid.
    $_SESSION["loggedin"] = true;
    $_SESSION["username"] = $db_query['name'];
    $_SESSION["the_usr_id"] = $db_query['user_id'];
    $_SESSION["userID"]  = $db_query['user_id']; // ADDED DUE TO DESCRIPTION ("PROB WILL BE OK")
    return true;
}



//This method seems to just be a copy of the method above, why does it exist?
//The only difference is $_SESSION["loggedin"] = true; which you could just do above.
//function setSessionVarables($pdo) {
//...
//}
//--deleted


function isRemembered() {
    //Instead of a separate remember cookie, just check if the token cookie exists.
    //if ($whatever){ return true; } else { return false} can be simplified to just return $whatever
    return isset($_COOKIE['token']);
}
?>

Sorry Ginerjm, just having been doing it that long (PHP).

Edited by oz11
Link to comment
Share on other sites

Sorry about the late reply, i have just spent ages solving the other error messages dotted all over my site and had a mental health issue before .. but feeling good and stable now.

Like i suggested i added this config...

Quote

 error_reporting(E_ALL); 

ini_set('display_errors', '1');

and got these results which i think are relative .. 

233204_Screenshotfrom2022-12-1621-04-52.png.c558a80cf8e034056706f21b6b2cfa8b.png

 

Current code [remember_token.php]:

<?php
 function setRememberMeToken($pdo, $user_id) {
    $token = bin2hex(random_bytes('25'));

    $expirationDate = time() + (86400 * 7); // <-- 7 days later (make sure your comments are accurate)
    setcookie('token', $token, $expirationDate, "/");
    //$_COOKIE['token'] = $token;
    $test = true;

    $to = date('Y-m-d', $expirationDate);

    $sql = "INSERT INTO `user_token` (`user_id`, `expires`, `tokenHash`) VALUES (?, ?, ?);";
    $stmt= $pdo->prepare($sql);
    $stmt->execute([$user_id, $to, sha1($token)]);
    //echo "test----------------";

        if (!setcookie('token', $token, $expirationDate, "/"))
    {
        echo "Could not set cookie for $token using $expirationDate - aborting";
       // exit();
    } else {
        echo "Setcookie ran ok";
    }
    if (isset($_COOKIE['tip3']))
        echo "<br>good cookie";
    if (isset($_COOKIE['token']))
        echo "<br>good cookie2";

}


function getRememberMeCheck($pdo) {
    $stmt = $pdo->prepare("
    SELECT users.name, users.user_id
    FROM user_token, users 
    WHERE 
        tokenHash = ? 
        AND expires > NOW()
        AND users.user_id = user_token.user_id
    ");
    $stmt->execute([sha1($_COOKIE['token'])]); 
    $db_query = $stmt->fetch();
    
    if (!$db_query){
        return false;
    }


    $_SESSION["loggedin"] = true;
    $_SESSION["username"] = $db_query['name'];
    $_SESSION["the_usr_id"] = $db_query['user_id'];
    $_SESSION["userID"]  = $db_query['user_id']; // ADDED DUE TO DESCRIPTION ("PROB WILL BE OK")
    return true;
}





function isRemembered() {
    return isset($_COOKIE['token']);
}
?>

Current code [login.php]:

<?php
    $the_page = " - Login/ Register";

     session_start();
    include 'includes/top_bottom/header.php';

    if((isset($_SESSION["loggedin"]) &&  $_SESSION["loggedin"] == true) && (isset($_SESSION["username"]))) {
            //header('Location: dash.php');
        }

$base = basename(parse_url($_SERVER['HTTP_REFERER'],PHP_URL_PATH));
?>


        <center>
<?php include 'includes/logo.php'; ?><!--<img src="mark.png" alt="beta project" width="80px;" style="margin-left: -184px; margin-bottom: 150px;">--><br>

<h2>Login/ register</h2>
<?php

if($_SERVER["REQUEST_METHOD"] == "POST"){
    $username = trim($_POST["username"]);
    $password = trim($_POST["password"]);

    // Check if username is empty
    if(empty(trim($_POST["username"]))){
        echo $username_err = "<span id='notification'>Please enter username.</span> ";
    } else{
        $username = trim($_POST["username"]);
    }
    
    // Check if password is empty
    if(empty(trim($_POST["password"]))){
        echo $password_err = "<span id='notification'>Please enter your password.</span> ";
    } else{
        $password = trim($_POST["password"]);
    }
    // continue...
    if(empty($username_err) && empty($password_err)){
        $sql = "SELECT user_id, name, password, active FROM users WHERE name = ?";
        $result = $pdo->prepare($sql);
        $result->bindParam(1, $_POST["username"]);
        $result->execute();
        $user = $result->fetch();

        if(!password_verify($_POST['password'], $user['password'])){
            echo "<span id='notification'>Invalid username/password.</span> ";
        }  else {
            if($user['active'] == '1') {
              $_SESSION["loggedin"] = true;
              $_SESSION["username"] = $_POST["username"];
              $_SESSION["userID"] = $user['user_id'];
              // cookie stuff
              if (isset($_POST['remember-me'])){
                echo setRememberMeToken($pdo, $user['user_id']); // <----- set token
                echo "<--woo";
              }
  
              echo "Hey ".$_SESSION["username"].". You are Logged in, redirecting in a moment or click <a href='dash.php'>here</a> to be taken to your dashboard.";
              //header("location:loggingin.php?id=true");
              include 'includes/top_bottom/footer.php';
              exit();
          }else {
            echo "User not active.";
          }
        }
    }
}
         

:)

 

Edited by oz11
added "login.php"
Link to comment
Share on other sites

Just tried with seven parameters (max all) based on the manual..

function setRememberMeToken($pdo, $user_id) {
    $token = bin2hex(random_bytes('25'));

    $expirationDate = time() + (86400 * 7); // <-- 7 days later (make sure your comments are accurate)
    setcookie("token", $token, $expirationDate, '/', 'localhost', true, true);
    $test = true;

    $to = date('Y-m-d', $expirationDate);

    $sql = "INSERT INTO `user_token` (`user_id`, `expires`, `tokenHash`) VALUES (?, ?, ?);";
    $stmt= $pdo->prepare($sql);
    $stmt->execute([$user_id, $to, sha1($token)]);
    //echo "test----------------";

        if (!setcookie("token", $token, $expirationDate, "/"))
    {
        echo "Could not set cookie for $token using $expirationDate - aborting";
       // exit();
    } else {
        echo "Setcookie ran ok";
    }
//    if (isset($_COOKIE['tip3']))
 //       echo "<br>good cookie";
//    if (isset($_COOKIE["token"]))
//        echo "<br>good cookie2";

}

Still getting errors. As you can see I'm using your testing method.

Screenshot from 2022-12-16 21-38-33.png

Edited by oz11
Link to comment
Share on other sites

You cannot set a cookie after you've already sent output.  Cookies are part of the headers (ie, setcookie just turns into header('Set-cookie: ...')) so they must come before any other script output.

That's what those errors are telling you.  You have output starting in colourmodes.php on line 32 which is preventing your cookie from being set.

You need to re-structure your application so you  can set your cookies before anything else happens that would cause output to be sent.

Link to comment
Share on other sites

Why do you set the cookie twice and do it differently each time?  I see one of them is still telling you that it's not working but the other one you did not alter to use an if to test the result.

Those error messages about output being alread sent.  That could also be the error messages I'm having you output once we resolve this issue.

Link to comment
Share on other sites

Whey. Seems like something is happening...

Oky doky. Cookies seem to be working now.. could  I ask of another question, does anyone know what this Error message could suggest: (once I've logged in and sent to the dashboard). I've cleaned a fair few today but cannot solve this alone seemingly ..

 

1447690790_Screenshotfrom2022-12-1622-23-44.png.facb593a3e8060e7d1186ca2b2431715.png

_________

ginerjm.. I'm still getting this result even when cookies have indeed been set.

1617867883_Screenshotfrom2022-12-1622-15-00.png.ccbb3507557222a01b5e3788b986fe68.png

 

@ ginerjmoh...

And i define the cookie twice as it stops me needing to refresh the page for the cookie to be set. A hack i got from someone on SO,.

Edited by oz11
Link to comment
Share on other sites

6 hours ago, oz11 said:

IDK man. :facewall::shrug: Looks ok to me https://www.w3schools.com/php/func_network_setcookie.asp

I don't understand.. Where do I need a boolean here? 

Please don't ever use w3schools as documentation for anything related to PHP.  The PHP manual is complete and well written, and also tends to have some excellent comments illustrating use or warning of gotchas.

For example, the manual page says this:

Quote

If output exists prior to calling this function, setcookie() will fail and return false. If setcookie() successfully runs, it will return true. This does not indicate whether the user accepted the cookie.

So it looks from your recent test that something has already sent the http header prior to trying to set the cookie.  That won't work.

Irrelevant to your problems, my advice on setting the time, as a more readable and simple solution:

$expirationDate = strtotime('+7 days') // <-- 7 days later (make sure your comments are accurate)

 

Where are you running this code during development?  Are you by chance using a localhost environment?  Since you aren't setting the domain in your setCookie, it is a long standing and well known issue that cookies require a valid domain, and "localhost" is not valid as it has no TLD   (.something).  

At this point, there are 3 recommended choices for a tld configuration you would make on your workstation.  (.test, .example or .dev).   .test and .example are reserved in the RFC's so there is no issue adding a domain to your workstation in a "/etc/hosts" files mapping it to 127.0.0.1.  .dev was purchased by Google, and is unused, so many people have decided to use that for development, and is known to work fine and have no conflicts.  I personally use www.something.test for development projects, so I'll map both 'something.test' and 'www.something.test' in my /etc/hosts file.   

 

Link to comment
Share on other sites

Cleaned up the errors.. and deleted the content of coloumodes.php, changed it around abit and re placed it in the page... Worked without it so just had to fix it up.

 

Anyway, since following the error it became clear! But with the help you you guys gizmola and ginerjm. So much thanks for your advice. 

PS: cant believe i didn't know about error reporting, never used it before and makes me feel more secure now.

:thumb-up:

 

Going to sleep now, at it all day and has been like 10 hours.. lucky i can go to bed with a clear mind. Again, thanks ginerjm and gizmola :) 

 

Edited by oz11
Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.