Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

advanced user authentication using sessions

Tags:

php

session

login

I am setting up a website that has 3 types of users:

-those who are registered and are subscribed for current month
-those that are registered, but are not subscribed for current month
-users that are not registered (you cant be subscribed if you are not regitered)

I've created code that identifies these 3 kinds of users and acts appropriately. My question is, is this the way to go? I've never done similar thing before. Or should I reprogram my approach?

//login.php

//connect to database and see if a user and password combination exists. Store $exists=0 if not, and $exists=1 if it exists.
session_start();

$conn = new mysqli($hn,$un,$pw,$db);
if ($conn->connect_error){
    die($conn->connect_error);
}
$query = "SELECT COUNT(1) as 'exists',expiration_date FROM table WHERE email = ? AND password = ?;";
$stmt = $conn->prepare($query);
$stmt->bind_param("ss", $email, $password);

$email = $_POST["email"];
$password = hash("hashingalgorithm", "salt".$_POST["password"]."salthere");

$stmt->execute();
   /* Get the result */
$result = $stmt->get_result();
$num_of_rows = $result->num_rows;
$row = $result->fetch_assoc();
$exists = $row["exists"];
$expiration_date = $row["expiration_date"];

/* free results */
$stmt->free_result();

/* close statement */
$stmt->close();
$conn->close();

date_default_timezone_set('Europe/Berlin');


if ($exists==0){
    echo "Wrong email or password";
    $_SESSION['loginerror'] = 2;
    header('Location: https://www.homepage.com/login'); 
}else if ($exists){
    if (strtotime($expiration_date) < (strtotime("now"))){//logged in, but not subscribed
        session_destroy();
        session_start();
        $_SESSION["authenticated"] = true;
        header('Location: https://www.homepage.com');
    }else{//logged in and ready to go
        $_SESSION["authenticated"] = true;
        $_SESSION["email"] = $email;
        header('Location: https://www.homepage.com');
    }
}else{
    echo "An error with has occured.";
} 

Then on every single page on my website I use this code, to see what kind of user has visited me

session_start();
if(isset($_SESSION["authenticated"]) && isset($_SESSION["email"])){ 
    $email = $_SESSION["email"];

    //connect to database and fetch expiration_date for a user with $email. Store it in $expiration_date

$conn = new mysqli($hn,$un,$pw,$db);
    if ($conn->connect_error){
        die($conn->connect_error);
    }
    $query = "SELECT expiration_date FROM table WHERE email = ?;";
    $stmt = $conn->prepare($query);
    $stmt->bind_param("s", $email);

    $email = $_SESSION["email"];
    $stmt->execute();
    /* Get the result */
    $result = $stmt->get_result();
    $num_of_rows = $result->num_rows;
    $row = $result->fetch_assoc();
    $expiration_date = $row["expiration_date"];
    /* free results */
    $stmt->free_result();
    /* close statement */
    $stmt->close();
    $conn->close();
    date_default_timezone_set('Europe/Berlin');

    if (strtotime($expiration_date) < (strtotime("now"))){//logged in, but not subscribed
        session_destroy();
        session_start();
        $_SESSION["authenticated"] = true;
        header('Location: https://www.homepage.com');
    }else{  //html for subsribed and registered user
    echo <<<_END
    //html here
    _END;
    }
}else if(isset($_SESSION["authenticated"]) && !isset($_SESSION["email"])){
        // user is logged in, but not subscribed;
        echo <<<_END
        //htmlhere
        _END;
}else{// user is not registered nor is subscribed
        echo <<<_END
        //htmlhere
        _END;
}

The code works, but I am worried about accessing database on every single page once the user registers and is subscribed. I am in effect penalizing users for registering and subscribing. Is there a better, performance wise, way to handle this kind of problem?

like image 486
sanjihan Avatar asked Feb 21 '17 21:02

sanjihan


People also ask

Should I use sessions or JWT?

One of the “issues” with sessions is scalability. The argument is that sessions are stored in memory and servers are duplicated to handle the application load, therefore, limiting the scalability of the application. JWT, on the other hand, has higher scalability due to its statelessness.

What is the difference between session based authentication and token based authentication?

Session based authentication: Because the sessions are stored in the server's memory, scaling becomes an issue when there is a huge number of users using the system at once. Token based authentication: There is no issue with scaling because token is stored on the client side.

What is an example of ways to secure session management?

To secure session managementImplement a session timeout and force re-authentication when users are inactive to mitigate the risk of an attacker using a hijacked session for a long time.


1 Answers

The solution here is to check for subscribed users (only on the first page where they login to your website) i.e. inside login.php you could use,

// ...your previous code
session_start();
// initialize session variables
$_SESSION['subscribe_date'] = $_SESSION['authenticated'] = false;
if ($exists == 0){
    echo "Wrong email or password";
    $_SESSION['loginerror'] = 2;
    header('Location: https://www.homepage.com/login'); 
} else if ($exists){
    $_SESSION["authenticated"] = true;
    if (strtotime($expiration_date) > (strtotime("now"))){ //logged in,& subscribed
        $_SESSION["email"] = $email;
        $_SESSION['subscribe_date'] = $expiration_date;
    } else {  //logged in and not subscribed, do nothin!
    }
    header('Location: https://www.homepage.com');
} else {
    echo "An error has occured.";
} 

Then, on every other page, all you need to do is only check for $_SESSION['subscribe_date'] instead of firing a query each time

if(!empty($_SESSION["subscribe_date"]) && strtotime($_SESSION["subscribe_date"]) > (strtotime("now"))) {
 // html for subscribed and registered user
} else if (!empty($_SESSION["authenticated"])) {
 // html for registered user
} else {
 // html for unregistered user
}

Also, note that I have removed session_destroy(); A very bad idea to call it on every page. You can unset session variables instead if needed. i.e. unset($_SESSION["email"]); You should call session_destroy(); only at the end when the user logs out. Check out the warning-section for session_destroy()

like image 148
Niket Pathak Avatar answered Sep 21 '22 02:09

Niket Pathak