How to authenticate securely by session tokens and cookies? updated - php

I tried to write my own authentication method (school project), and I'm stuck.
Please advise, how to solve a secure authentication:
There is an index.php which contains everything that needs to be "protected". I will copy the relevant parts of my code here.
updated index.php
session_start();
function checkUserAuth(){
$authStatus = false;
if (isset($_SESSION['PHPSESSID'])){
if ($_SESSION['PHPSESSID'] == $_COOKIE['PHPSESSID']){
$authStatus = true;
}
}
return $authStatus;
}
if(!checkUserAuth()){
include_once(dirname(__DIR__).'/admin/authentication/login.php');
exit();
}
If the checkUserAuth() determines, that there is no properly authenticated user, will include the login.php and stop the rest of the script.
updated login.php:
if(array_key_exists($username, $users) && password_verify($password, $users[$username])){
$_SESSION['PHPSESSID'] = $_COOKIE['PHPSESSID'];
$_SESSION['login_user'] = $_POST['user'];
What I imagine that might happen, is that if the login details are correct, the login.php sets a cookie, and refreshes the page. Then the index.php will detect the cookie, and skip the login part.
The login is pretty much figured out, and thanks to Juned, I think it is working now. However I don't know how secure is this?
On a scale from 1 to very, how wrong I am?

There are loads of ways of doing this. The below pseudocode is not the most efficient but should work and I don't think what you've done above will actually work.
Does this help?
login.php pseudocode
<?php
session_start(); // this function checks if there's a session ID already set, if not, sets one.
if(array_key_exists($username, $users) && password_verify($password, $users[$username])){
// do your login details checking here
// if login details correct
// set a flag in the $_SESSION superglobal and whatever else you want to store about the user like their username e.g.
$_SESSION["loggedIn"] = true;
$_SESSION["username"] = "$_POST['user']"; // better practice to fetch a clean version from your database
//else return user to login page
}
?>
index.php pseudocode
<?php
session_start(); // this will fetch the session ID and other variables that you might have set e.g. username, logged in status
function checkUserAuth(){
$authStatus = false;
if (isset($_SESSION['loggedIn']) && $_SESSION['loggedIn'] === true){
$authStatus = true;
}
return $authStatus;
}
if(!checkUserAuth()){
// redirect to login page. e.g.
header('Location: login.php');
exit;
}
?>

Related

PHP - Is $_SESSION[] a reliable way to secure php content?

I've tried to be as specific as possible, but I'm sorry that the subject of my question may be broad.
I got used to a habit of sending variables using the $_GET['variable'], for instance, let's say I'm using ajax to get some information from a database, I would probably do something like this:
xmlhttp.open("GET","read.php?option=someoption",true);
And then I would set the PHP page in a way that behave differently according to the $_GET['option'] it would receive.
I then realised that any logged-in user could type the URL and directly modify the database, so I've set some additional $_SESSION['redirect'] variables before each redirection to help prevent access to php pages from URL. By doing a quick ajax call to a "prevent.php" page that would do something like so:
$_SESSION['redirect'] = "true";
header("Location: page.php");
And then having it set this way in the page.php for instance:
if ($_SESSION['redirect']==true) {
// access the database
}
else {
// deny access
}
Is this a reliable way of doing things, or is there a more professional way to sort it out?
No it's not a secure way of doing it.
Here's an example of how you could achieve a secure user system in the simplest of forms:
login.php
<?php
session_start();
$user = isset($_POST['username']) ? $_POST['username'] : false;
$pass = isset($_POST['password']) ? $_POST['password'] : false;
# Check credentials
if (validCredentials($user, $pass)) {
# Credentials are valid
# Set isAdmin session for the user 'admin'
# This is hardcoded for simplicity but
# you could read a value from a database
# and set this session dynamically.
if ($user === 'admin') {
$_SESSION['isAdmin'] = true;
}
# Generate CSRF token (see appendix)
# heads up: random_bytes() is a PHP7 function.
$_SESSION['token'] = bin2hex(random_bytes(32));
# Set logged in session for every user
$_SESSION['user'] = $user;
echo 'Successfully logged in!<br />';
echo 'Go to the user page.';
}
admin-page.php:
<?php
session_start();
if (isset($_SESSION['isAdmin']) && $_SESSION['isAdmin'] === true) {
echo 'Only the admin can see this.';
} else {
echo 'You are either not logged in or you don\'t have the permission to view this page.';
}
user-page.php:
<?php
session_start();
if (isset($_SESSION['user'])) {
$token = $_SESSION['token'];
echo 'Only logged in users can see this. <br />';
echo 'Log me out.';
} else {
echo 'You are not logged in.';
}
Appendix:
Make sure that you protect yourself against CSRF attacks:
For example an insecure way of logging an user out would be:
logout.php:
<?php
session_start();
if (isset($_SESSION['user'])) {
session_destroy();
}
Maybe you ask yourself why this is not secure.
The reason is because for every user the logout link is the same (example.com/logout.php).
So it's not hard at all to guess the logout link (well, we don't even have to guess, we already know for sure).
An attacker could disguise the logout link and as soon as you click on it you would be logged out.
It's very important to understand that the logout is just one example.
Think of a more severe action like deleting a user etc.
So this concept applies to every action an authenticated user can do.
To be safe, you can generate a token as soon as the user has logged in.
For every action taken you then check if the token in the request matches the one you generated.
This way the logout link is unique for every user (example.com/loogut.php?token=random_token_generated_at_login) and is only hardly guessable by an attacker.
safe-logout.php:
<?php
session_start();
if (isset($_SESSION['user'])) {
# Check if the user specified token matches ours
$token = isset($_GET['token']) ? $_GET['token'] : false;
if ($_SESSION['token'] === $token) {
session_destroy();
echo 'Successfully logged out!';
} else {
# We dont logout because the token was not valid
}
}
And NO: a POST request is just as susceptible as a GET request.
So make sure you check the token for every action, regardless of the HTTP method used.

Logged in value issue between PHP scripts

I am reading a lot regarding the best practice to monitor when a user is logged in or not.
Currently i am trying to use a variable in a session like below:
login.php
<?php
session_start();
//I set that variable to false
$_SESSION['LOGGED_IN'] = FALSE;
{follows some code that checks the username and the password provided by the user
in an HTML form with POST request against the records of the database. If a match is
found then it allows the user to proceed with the loggin}
if($statement->rowCount() = 1) //
{
session_regenerate_id(true);
$_SESSION['LOGGED_IN'] = TRUE;
header('Location: mainpage.php');
}
else
{
echo "wrong username or password";
}
?>
mainpage.php
<?php
session_start();
if(($_SESSION['LOGGED_IN'] == TRUE) && isset($_SESSION['LOGGED_IN']))
{
echo "You are now logged in!";
}
else
{
echo "You are not logged in. Please retry.";
}
?>
The problem is that when i use a correct pair of credentials SOMETIMES i log in getting the "You are now logged in!" message, and sometimes using the same credentials i get the "You are not logged in. Please retry.".
I've added that message in the else statement on purpose. Normally there i will insert a redirection to the login page.
I am getting confused because this is an error that i shouldn't have. In the login.php script i am making sure that in order to redirect to the mainpage.php the $_SESSION['LOGGED_IN'] = TRUE. So that value should be transferred to the mainpage.php as TRUE and not FALSE.
What am i missing here?
And a general question regarding loggin:
Is it better to keep the login value (TRUE or FALSE) in a session or use a table in MySQL with a flag indicating when a user is logged in or not?
Thanks!

keeping a LDAP user logged in with PHP session

UPDATED According to advice below. But still not working. Any help?
My company uses Active Directory LDAP and I'm using adLDAP to authenticate the user to login to this website.
So far, it works.. but every time they visit the page they must login again. The solution to this, I know is sessions. But I can't figure out what to store in the session in order to keep the user logged in.
This is included at the top of my login.php page:
auth.php
<?php
//include LDAP authenication script
require_once('LDAP/adLDAP.php');
$adldap = new adLDAP();
$username = $_POST['account'];
$password = $_POST['password'];
$authUser = $adldap->authenticate($username, $password);
$userinfo = $adldap->user_info($username, array("*"));
if ($authUser == true) {
$_SESSION['LDAP']['login'] = true
}
?>
Also at top of every page I have this:
<?php
if (empty('LDAP')) session_start();
if (!isset($_SESSION['LDAP']['login'] && $_SESSION['LDAP']['login'] !== true) {
header('Location: login.php');
exit; // dont forget the exit here...
}
?>
Right now, everytime I visit my index page index.php I log in, and I'm redirected to the main page. It works perfectly. But if I refresh the page, I'm asked to login again.
What do I store into a session so I don't have to log in everytime I refresh the page?
I know it starts with:
session_start();
But I don't know what to store in it?
You should only authenticate/include LDAP on your login page..
if success set a $_SESSION['LDAP']['login'] = true;
And check on every page with this.
if (!isset($_SESSION['LDAP']['login'] && $_SESSION['LDAP']['login'] !== true) {
header('Location: login.php');
exit; // dont forget the exit here...
}

php session lost after submitting form

The code below page keeps session on GET requests or refreshing browser, but when I submit a form the session data is lost.
$user=$_POST['user']; $pass=$_POST['pass'];
if ($_POST['user'])
{ if($user==$un and $pass=$pw)
{ $_SESSION['uid']=$Xid;header('Location: '.$uri.'?welcome'); }
else { $msg="chybny login"; }
}
if(isset($_GET['logout'])) { session_destroy(); header('Location: '.$uri); }
$cnt=$_SESSION['cnt']+1; $_SESSION['cnt']=$cnt;
Above is the code for login which re-directs me to the welcome page as it was verified, however the session is lost. If I just refresh or repeatedly load the page without submitting, the session holds by echoing the session variable cnt (counts up 1,2,3,...)
After submitting the form, I see session is lost and too cnt variable is reset?
I usually don't work with session directly try the following, place it a the top of your script :
session_start();
$uid = $_SESSION['uid'];
$cnt = $_SESSION['cnt'];
then work with the variable instead
The problem is likely your 'and' statement. It should be &&. The condition is not going to be true.
If you're 100% sure the code is all fine and the PHP.ini is the problem, based on your comments above. Look at this link at check the settings in the .ini http://php.net/manual/en/session.configuration.php
To pass the current session to the next page... I believe is what you are asking...
You are currently not passing the session to the next page and use session_start() at the top of the next page.
Change line 4 to:
{ $_SESSION['uid']=$Xid;header('Location: '.$uri.'?'.SID.'&page=welcome'); } // Where "page" is the name of the data you are retrieving
Or, you can save the session data to a cookie and then retrieve it on the next page.
You can alternately name the session when you use session_start("NameHere") on each page, however if the visitor has recently visited and the session not destroyed, they may see parse errors, if you have them enabled.
First of all, make sure that the the first thing you do on every page is to start a session (I recommend calling it once in a header file that you require on all of your sub sites).
So that you have session_start(); everywhere in the system.
Second of all, tighten up your code; make it easier to read. Something like
$userName = isset($_POST['userName']) ? $_POST['userName'] : false;
$password = isset($_POST['password']) ? $_POST['password'] : false;
$logout = isset($_POST['logout']) ? $_POST['logout'] : false;
$url = '../index.php';
if(!($logout))
{
if($userName && $password)
{
if($userName == $un && $password == $pw)
{
$_SESSION['loggedIn']=true;
$_SESSION['uid']=$Xid;
$_SESSION['message']="success";
}
else
{
$_SESSION['loggedIn']=false;
$_SESSION['message']="fail, incorrect login information.";
}
}
else
{
$_SESSION['loggedIn']=false;
$_SESSION['message']="fail ; username and password not submitted.";
}
header("Location: $url");
}
else
{
session_start();
session_destroy();
session_start();
header("Location: $url");
}
And if you want to display unqiue content depending on whether a user is logged in or not, then you can simply check if the login session is set or not, on each page, instead of modifying the header for that.

If isset $_SESSION goto this page?

Ok, having trouble here:
I created a login script, so after a person logs in then they will get direted to another page. And also, I have it redirecting them to the login page if they try and access one of those other pages.
My problem is, if a user is logged in and stumbles to the login page again --by accident-- I would like for it to recognize that the user is logged in and redirect them to that next page (which is index2.php) ?? Having troubles :-(
Here is my code so far:
require_once "inc/functions.class.php";
$quickprotect = new functions('inc/ini.php');
if (isset($_SESSION['goAfterLogin'])){
$goto = $_SESSION['goAfterLogin'];
unset($_SESSION['goAfterLogin']);
}
else $goto = $quickprotect->settings['DEFAULT_LOGIN_SUCCESS_PAGE'];
if (isset($_POST[username])) {
if($quickprotect->login($_POST[username], $_POST[password])) header ("Location: $goto");
}
Here is how I store a users session in the functions page
public function is_logged_in() {
//Determines if a user is logged in or not. Returns true or false;
if ($_SESSION['logged_in'] === md5($this->settings[ADMIN_PW])) {
return true;
}
else return false;
}
You don't mention how you store your users in your session, but something like this should do it for you:
if(isset($_SESSION['user']))
{
header("Location: index2.php");
exit;
}
This will check if you have a user in your session, and if so, redirect to index2.php.
You need to change 'user' according to your session key.

Categories