Joomla 2.5 - Log user in without password - php

I'm building a custom joomla component and am looking into ways I can set a login session without using an account password. I already have:
$app = &JFactory::getApplication('site');
$result = $app->login(array(
'username' => 'james',
'password' => 'password'
));
Which obviously requires the users password. I have access to the user ID and username so either of these handles can be used. Is there another object or method I can use to log a user in or is there some custom solution I can use e.g manually set all required $_SESSION variables?
Thanks in advance, any help much appreciated :)

IMPORTANT: Is necesary to add the session Object after // Register the needed session variables
// Register the needed session variables
$session =& JFactory::getSession();
$session->set('user', $jUser);
Excellent, thx

//log user in
if(!JFactory::getUser()->id)
{
$email = (string)$response['linkedin']->{'email-address'};
$db = JFactory::getDbo();
$app = JFactory::getApplication();
$sql = "SELECT * FROM #__users WHERE email = " . $db->quote($email);
$db->setQuery($sql);
$result = $db->loadObject();
if($result->id)
{
$jUser = JFactory::getUser($result->id);
//$userarray = array();
//$userarray['username'] = $jUser->username;
//$userarray['password'] = $jUser->password;
//$app->login($userarray);
$instance = $jUser;
$instance->set('guest', 0);
// Register the needed session variables
$session =& JFactory::getSession();
$session->set('user',$jUser);
// Check to see the the session already exists.
$app->checkSession();
// Update the user related fields for the Joomla sessions table.
$db->setQuery(
'UPDATE '.$db->quoteName('#__session') .
' SET '.$db->quoteName('guest').' = '.$db->quote($instance->get('guest')).',' .
' '.$db->quoteName('username').' = '.$db->quote($instance->get('username')).',' .
' '.$db->quoteName('userid').' = '.(int) $instance->get('id') .
' WHERE '.$db->quoteName('session_id').' = '.$db->quote($session->getId())
);
$db->query();
// Hit the user last visit field
$instance->setLastVisit();
//return true;
$app->redirect('index.php?option=com_community&view=profile');
}
else
{
$url = "index.php?option=com_community&view=register";
$app->redirect($url,'We did not find your email address in our system. Please register.');
//echo "redirect to registration page";
//exit();
//$url = 'index.php?option=com_users&view=registration&name=' . $user_profile['name'] . '&username=' . $user_profile['username'] . '&email=' . $user_profile['email'];
//$url = JRoute::_($url);
//$app->redirect($url);
}
}

Related

PHP session not holding value on page change

I know there are quite a few posts about this topic but none of them have fixed my issue.
I have WAMP server running on my windows computer. I've created a login system that is able to set PHP sessions and verify that they are working while on the page that they were created. Once I change to a different page, either by typing in the URL or a javascript function I lose the session.
Here is my test.php that logs a user in
require_once('config.php');
$user = new User();
$result = $user->login('email#gmail.com', 'mysecretpassword');
echo $result;
echo '</br>';
$result = $user->isLoggedIn();
echo $result;
This is the function that actually logs the user in
public function login($email, $password) {
// Hash Password
$password = $this->hashPassword($password);
// Check if email and password match
$query = "SELECT id, confirm_email FROM users WHERE email = ? AND password = ?";
$a_bind_params = array($email, $password);
$a_param_types = array('s','s');
$results = $this->db->select($query, $a_bind_params, $a_param_types);
// If we didnt get a result then email/password must be wrong
if(count($results) == 0) return 1;
// Now check that they verrified their email
if($results[0]['confirm_email'] == 'N') return 2;
// User is real and everything is good
// Update login Date
$a_bind_params = array(date('Y-m-d H:i:s'), $results[0]['id']);
$a_param_types = array('s','s');
$query = "UPDATE users SET login_at = ? WHERE id = ?";
// There was a problem updating their login table so just fail the login
if(!$this->db->update($query, $a_bind_params, $a_param_types)) return 3;
// Login user
Session::set("user_id", $results[0]['id']);
session_regenerate_id(true);
Session::set("login_fingerprint", $this->_generateLoginString ());
return 0;
}
Here is the function that checks if the user is logged in
// Checks if user is logged in
public function isLoggedIn() {
//if $_SESSION['user_id'] is not set return false
if(Session::get("user_id") == null)
return false;
$loginString = $this->_generateLoginString();
$currentString = Session::get("login_fingerprint");
if($currentString != null && $currentString == $loginString)
return true;
else {
//destroy session, it is probably stolen by someone
$this->logout();
return false;
}
}
Here is the Session function that creates a session
public static function startSession() {
ini_set('session.use_only_cookies', true);
$cookieParams = session_get_cookie_params();
session_set_cookie_params(
$cookieParams["lifetime"],
$cookieParams["path"],
$cookieParams["domain"],
SESSION_SECURE,
SESSION_HTTP_ONLY
);
session_start();
session_regenerate_id(true);
}
These are the function that set/get the user session
public static function set($key, $value) {
$_SESSION[$key] = $value;
}
public static function get($key, $default = null) {
if(isset($_SESSION[$key]))
return $_SESSION[$key];
else
return $default;
}
Finally this is my config.php file that actually calls session_start() and include some constants
// REQUIRE ALL FILES
require_once("ClassSession.php");
require_once("ClassDatabase.php");
require_once("ClassUser.php");
Session::startSession();
If I navigate to another page called test.php
include "config.php";
$user = new User();
if($user->isLoggedIn()) echo 'logged in';
else 'Not logged in';
The session is lost and the user is not logged in anymore.
I've checked my sessions.save_path in PHP.ini and have checked the wamp64/temp folder and my sessions are being stored in there. I am also calling session_start() on every page because I am including config.php on both the test pages. Not sure why I am losing my sessions.
EDIT
I forgot to mention what is actually happening. When I login the user I look up their user_id from the database and store that into $_SESSION['user_id']. When I access $_SESSION[user_id] from the page that logged the user in I get back the correct value. However, when I change to another page $_SESSION['user_id'] is null.
UPDATE
session_regenerate_id(true) is not the problem.
Here are my Session settings when printing php_info()
session_set_cookie_params(
$cookieParams["lifetime"],
$cookieParams["path"],
$cookieParams["domain"],
SESSION_SECURE,
SESSION_HTTP_ONLY
);
Check values here. What is SESSION_SECURE const value? Maybe you are restricting cookie usage to https only and your site is on http.
I just wrote a very basic PHP code to give you an idea how this can be quickly built. You should change the parameters, use mysqli or PDO or ORM whichever you like but the basic idea remains the same. Use secure cookies, follow the best practices to hide what needs to be secured.
Create a php file call it functions.php and paste the following code in it
<?php
session_start();
function createsessions($email, $password, $loginId)
{
//Add additional member to Session array as per requirement
//session_register();
$_SESSION["email"] = $email;
$_SESSION["password"] = $password;
$_SESSION["loginId"] = $loginId;
//Add additional member to cookie array as per requirement
setcookie("loginEmail", $_SESSION['loginEmail'], time() + 31536000, "/", ".example.com", 0, true);
setcookie("password", $_SESSION['password'], time() + 31536000, "/", ".example.com", 0, true);
setcookie("loginId", $_SESSION['loginId'], time() + 31536000, "/", ".example.com", 0, true);
}
#Authenticate User
function confirmUser($email_address, $password)
{
if (mysql_num_rows(mysql_query("select * from TABLE where email ='" . $email_address . "' and password =MD5('" . $password . "')"))) {
$loginstatus = 1; //account exists, login
return $loginstatus;
} else {
$loginstatus = 0; // Incorrect Credentials
return $loginstatus;
}
}
#Function to check login status
function checkLoggedin()
{
if (isset($_SESSION['email']) && isset($_SESSION['password']))
return true;
elseif (isset($_COOKIE['email']) && isset($_COOKIE['password'])) {
if (confirmUser($_COOKIE['email'], $_COOKIE['password'])) {
$sql_id = mysql_query("select id, email, password from TABLE where email ='" . $_COOKIE['email'] . "' and password ='" . $_COOKIE['password'] . "'");
$sql_array = mysql_fetch_row($sql_id);
#Register Session & Cookies Variables
$loginId = $sql_array[0];
$email = $sql_array[1];
$password = $sql_array[2];
//Clear all sessions and cookies first
clearsessionscookies();
createsessions($email, $password, $loginId);
return true;
} else {
clearsessionscookies();
return false;
}
} else
return false;
}
#Logout and clear session and cookies data
function clearsessionscookies()
{
unset($_SESSION['email']);
unset($_SESSION['password']);
unset($_SESSION['loginId']);
setcookie("PHPSESSID", null, time() - 31536000, "/", ".example.com", 0);
setcookie("email", null, time() - 31536000, "/", ".example.com", 0);
setcookie("password", null, time() - 31536000, "/", ".example.com", 0);
setcookie("loginId", null, time() - 31536000, "/", ".example.com", 0);
session_unset();
session_destroy();
ob_end_flush();
}
?>
createsessions() and clearsessionscookies() helps in handling session creation and deletion. Replace example.com to your cookie domain.
From your HTML Page, make an AJAX Call to a function and put the following code in it
<?php
#AJAX Call to this function
function checkLogin()
{
// Don't forget to protect against MySQL injection
$user_email = mysql_real_escape_string($_POST['emailaddress']);
$password = mysql_real_escape_string($_POST['password']);
if ($user_email == '' || $password == '') {
echo "Invalid email address or password. Please try again.";
$hasError = true;
}
$loginstatus = confirmUser($user_email, $password);
if ($loginstatus == 0) {
echo "Invalid ID or password. Please try again.";
$hasError = true;
} else // Login Now
{
if ($hasError != true) {
#Get User Details In Session
$sql_id = mysql_query("select loginId, email, password from TABLE where email ='" . $user_email . "' and password =MD5('" . $password . "')");
$sql_array = mysql_fetch_row($sql_id);
#Register Session & Cookies Variables
$loginId = $sql_array[0];
$email = $sql_array[1];
$password = $sql_array[2];
//Create Fresh sessions and cookies
createsessions($email, $password, $loginId);
//Redirect to Dashboard or wherever you want the customer to go post authentication
}
}
}
?>
I have purposely kept the LoginID so you can specifically handle the particular record for referencing with other tables you might have associated with the user table.
I hope this will work and help you keep the user logged in for the specified period in the cookie.
Your problem could be
session_regenerate_id(true);
This is going to delete your session and update it with a new session id and you are going to lose the association with any session data for the old session id.
From the docs for the parameter to this function.
delete_old_session
Whether to delete the old associated session file or not.
You said config.php calls session_start(); however I see you are using
ini_set(use.cookie, true)
That is wrong and causing your issue.

Joomla 2.5 create user in php script without email address

I have a a php function that works for creating a new user in Joomla 2.5. This function is used to synchronize an external customer database with Joomla.
The new requirement is that the email address needs to be an optional field. I can't seem to get the JFactory function to work without an email address. Is there another way to get the user created?
function add_joomla_user($username, $email, $name, $password, $group) {
// Creates a new user in Joomla database with passed in information
$return_message = '';
$mainframe =& JFactory::getApplication("site");
$mainframe->initialise();
$user = JFactory::getUser(0); // it's important to set the "0" otherwise your admin user information will be loaded
jimport('joomla.application.component.helper'); // include libraries/application/component/helper.php
$usersParams = &JComponentHelper::getParams( 'com_users' ); // load the Params
$userdata = array(); // place user data in an array for storing.
$userdata['username'] = $username;
$userdata['email'] = $email;
$userdata['name'] = $name;
$userdata['password'] = $password;
$userdata['password2'] = $password;
$defaultUserGroup = $usersParams->get('new_usertype', $group);
$userdata['groups']=array($defaultUserGroup);
$userdata['block'] = 0; // set this to 0 so the user will be added immediately.
if (!$user->bind($userdata)) { // bind the data and if it fails raise an error
JError::raiseWarning('', JText::_( $user->getError())); // something went wrong!!
$return_message = 'Error binding data: ' . $user->getError();
}
if (!$user->save()) {
JError::raiseWarning('', JText::_( $user->getError()));
$return_message = 'Error creating user: ' . $user->getError();
} else {
$return_message = 'Created user';
}
return $return_message;
}
Joomla user handling definitely requires a unique email address for each user. It's tricky and I somewhat hesitate to suggest this, but what you could do if it is missing is substitute a random string or a string generated based on information in your database (like the $userdata['email'] = $username . '#noemail';. That way they will be easy to find later. Of course this means password reset and other functions will never work, but that would be true anyway if the user has no email.

Redirecting logged in users

I have created profiles for users so that when a user logs in they are redirected to their own profile page.
login.php (relevant code only)
$MemberID = user_id_from_username($username);
$_SESSION['MemberID'] = $username;
header('location: member.php?username='.$username);
member.php
if (logged_in () === true){
echo "Welcome, ".$_SESSION['MemberID']. "!<br><a href='logout.php'>Logout</a>\n<a href='index.php'>Back to homepage</a></p>";
}
if(isset($_GET['username']) === true & empty ($_GET['username']) === false) {
$username = $_GET ['username'];
//check if user actually exisits
if (user_exists($username) === true) {
//get username from user id
$MemberID = user_id_from_username($username);
$profile_data =user_data($MemberID,'Name','Address','Postcode','DOB','Mobile','CoinsAvailable','Email','profile','OddJobName','Description','CoinValue','DaysAvailable');//Need to pull out stuff from oddjob table
echo $MemberID;
}else{
protect_page();
}
}
relevant functions:
function user_data($MemberID){ //pass in memberid to get info about user
$data = array();//data to be returned
$MemberID =(int)$MemberID;//creating int from this input
$func_num_args = func_num_args(); //count number of arguments from user data on init.php
$func_get_args = func_get_args();
if ($func_num_args >1) { //if more then 1, unset the first element of array
unset($func_get_args[0]);
$fields = '`' . implode('`,`', $func_get_args) . '`'; //taking array and converting to string
$data = mysql_fetch_assoc(mysql_query("SELECT $fields FROM `member`,`oddjob` WHERE member.MemberID = oddjob.MemberID AND member.MemberID = $MemberID"))or die (mysql_error());
//echo $MemberID;
return $data;
}
}
function logged_in() {
return (isset($_SESSION['MemberID'])) ? true : false; //Email
}
if (logged_in() ===true) {
$session_MemberID = $_SESSION['MemberID'];//grabbing value from login
$user_data= user_data($session_MemberID,'MemberID','Name','Address','Postcode','DOB','Mobile','CoinsAvailable','Email','Password','RepeatPassword','OddJobName','Description','DaysAvailable','profile');
exit();
}
All this code allows the user to be redirected to their own page, when they login their name is displayed along with other $profile_data information. Now I want the user to be able to update their own info by clicking on a link to update_info.php. But I don't know how to get the members username to appear in the URL when they visit update_info.php like it does when they log in.
In the member page (where the link is) I tried:
<a><?php header('location:update_info.php?username='.$username)?>">Update info</a></p>
But now when the user logs in they are redirected to update_info.php instead of member.php. Can anybody tell me how to fix this? Thanks.
Do you mean:
Update info
This passes the $username to the update_info.php page
Maybe you wanted to write this?
Update info</p>
All right.
Lets explain the basics on how to build a -basic- authentication. And then extend it to a safe one :)
1 - user logs in : You check the database if the credentials are allright.
If Yes -> $_SESSION['loggedIn'] = true;
2 - On every page you want to check if the person is logged in; you put a check:
if(!$_SESSION['loggedIn']) { header('location:login.php');}
Some food for thought:
You don't want to store 'just' a boolean on the clientside to check if logged in. You better generate a random session-id-string. Store this in a database and store this id in the $_SESSION['loggedin']. Instead of the simple check of the value of $_SESSION['loggedIn'] you now look up the stored session ID in the database for existince and availability.
Post Scriptum:
Don't nest functions in functions in functions.
$data = mysql_fetch_assoc(mysql_query("SELECT $fields FROMmember,oddjobWHERE member.MemberID = oddjob.MemberID AND member.MemberID = $MemberID"))or die (mysql_error());
This is not readable for us, but especially not for you. You better write it like this:
$sql = "SELECT $fields FROMmember,oddjobWHERE member.MemberID = oddjob.MemberID AND member.MemberID = $MemberID";
$res = mysql_query($sql) or die(mysql_error());
$data = mysql_fetch_assoc($res);
Post Post Scriptum:
Stop using the mysql_* functions in php. See the red box on this website? These functions are not supported anymore. And you better start using PDO; which by the way has also some checking (mysql injection) standard build in; and much more!

Mysql call stops all forms of output php

Hello, I'm kind of new to php, so don't bash on me, but I just can't figure out what the problem is with this code. So basically I have several forms of output, but as soon as I do anything with mysql ( even just connect and disconnect! ), it won't allow me to do any kind of output. It also won't allow me to redirect.
I tried taking all the code out between the mysql connect and disconnect code and it didn't help to resolve anything, However, as soon as I comment out the mysql connection code, all my outputs and redirects work! I'm trying to build a simple login script that gets the email and password from a form elsewhere. I would love to get this resolved so I could figure out if the rest of it works. And I know that 'header' will not work after echo; the echo and the file writes will not be there as soon as I can make sure this is working. Any help would be appreciated! Thanks!
<?php
/*
Login.php searches for the email address given by loginPage.php in the data base.
If the email is found and the password given by loginPage.php matches that stored
in the data base, a session will begin and the client will be redirected to the
main page.
*** INCOMPLETE ***
*/
echo "HELLO!";
$email = $_POST["email"];
$password = $_POST["password"];
$errorLog = fopen("login.txt", "w");
fwrite($errorLog, "***Sesion started***");
$mysql_id = mysql_connect("localhost", "root", "12131");
if (!$mysql_id)
{
die('Could not connect: ' . mysql_error());
}
mysql_select_db('informationStation', $mysql_id);
$results = mysql_query("SELECT password FROM Personals WHERE email = '" . $email . "';", $mysql_id);
if($results != null && $password == mysql_fetch_array($result))
{
$redirect = 'Location: http://127.0.1.1/main.php';
}
else
{
$redirect = 'Location: http://127.0.1.1/loginPage.php';
{
mysql_close($mysql_id);
fwrite($errorLog, "result: " . $results);
fwrite($errorLog, "redirect: " . $redirect);
fclose($errorLog);
header($redirect);
?>
Try this to get you started..
$results = mysql_query("SELECT password FROM Personals WHERE email = '" . $email . "'", $mysql_id) or die(mysql_error());
But you also need to read about sql injection.
And you should not store passwords in your database without salting and hashing them.
And you also need to use array syntax to access the data from your result...
$mysql = mysql_connect("localhost", "root", "12131") or die('Could not connect: ' . mysql_error());
mysql_select_db('informationStation', $mysql);
function loged($email, $password) {
$result = mysql_query("SELECT id FROM Personals WHERE email = '" . $email . "' AND password='" . $password . "'");
if(mysql_num_rows($result) != 1)
return false;
return true;
}
if(loged(mysql_real_escape_string($email), md5($password))) {
header('Location: http://127.0.1.1/mainPage.php');
exit;
}
header('Location: http://127.0.1.1/loginPage.php');
In this example you need to store users password using md5 encryption method (search for other more securely encryption methods).
Also we've escaped the email address against sql injection.
I've created a function which can be called every time you want to see if the user is loged in or not.
Note that this is not a complete login script. You will also need to make a login function where you'll have to start a new session for each user.

Custom PHP function to verify correct password in Joomla

I created a script outside of Joomla that can successfully generate a Joomla password:
// I copied the JUserHelper class from Joomla here
$salt = JUserHelper::genRandomPassword(32);
$crypt = JUserHelper::getCryptedPassword($password, $salt);
$psw = $crypt.':'.$salt;
My question is, how can I compare this new crypt:salt I generate above to a password of an existing user in the Joomla database, and know if the password supplied to the script above is the correct password for that user in the database?
In joomla 3.4.5:
if (!class_exists("JFactory")) {
define('_JEXEC', 1);
define('JPATH_BASE', dirname(__FILE__)); // specify path to joomla base directory here
define('DS', DIRECTORY_SEPARATOR);
require_once ( JPATH_BASE . DS . 'includes' . DS . 'defines.php' );
require_once ( JPATH_BASE . DS . 'includes' . DS . 'framework.php' );
$mainframe = & JFactory::getApplication('site');
$mainframe->initialise();
}
$user = JFactory::getUser(); // or: getUser($id) to get the user with ID $id
$passwordMatch = JUserHelper::verifyPassword($entered_password, $user->password, $user->id);
EDIT: I posted this before the previous reply showed.
You could always break apart the stored password from the salt as they're just separated by a ':' ?
If the page is outside of the Joomla framework you will need to include the framework which should be able to be accomplished with this (reference - codeblock below). If you are inside of the Joomla framework, skip past this block. However, I didn't test the referenced codeblock:
define( '_JEXEC', 1 );
define( 'DS', DIRECTORY_SEPARATOR );
define('JPATH_BASE', dirname(__FILE__).DS."..".DS.".." );
require_once ( JPATH_BASE.DS.'includes'.DS.'defines.php' );
require_once ( JPATH_BASE.DS.'includes'.DS.'framework.php' );
$mainframe =& JFactory::getApplication('site');
$mainframe->initialise();
In the framework you will need to look up the user by ID or username:
$user =& JFactory::getUser(username or id goes here);
Then if you have a match for $user you can simply do this access that user's password:
$user->password;
Then you can just compare with what your $psw
I believe that should help you on your way.
Are you looking to use this to log a user in with Joomla credentials to an external site or are you looking to log them in to a Joomla site?
One way would be to query the Joomla database directly to get a user's (salted and hashed) password, then compare. I think the below query should work for that, based on what I have seen from a few google searches. I have done this in Wordpress, so I'm assuming Joomla would be similar.
select 'password' from `jos_users` WHERE `username` = "Bob";
I am sorry to say that the above solution suggested is the worst
because JUserHelper::genRandomPassword(32) function is used to generate random passwords and it will be the different password each time when it is generated
So different password will be saved in the db while registering with the user when compared to the one which will be generted at the time of checking which will obviously doesn't match in any ways
This is how Joomla 2.5 Validates a password
See the plugin file : \plugins\authentication\joomla\joomla.php
function onUserAuthenticate($credentials, $options, &$response)
{
$response->type = 'Joomla';
// Joomla does not like blank passwords
if (empty($credentials['password'])) {
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message = JText::_('JGLOBAL_AUTH_EMPTY_PASS_NOT_ALLOWED');
return false;
}
// Initialise variables.
$conditions = '';
// Get a database object
$db = JFactory::getDbo();
$query = $db->getQuery(true);
$query->select('id, password');
$query->from('#__users');
$query->where('username=' . $db->Quote($credentials['username']));
$db->setQuery($query);
$result = $db->loadObject();
if ($result) {
$parts = explode(':', $result->password);
$crypt = $parts[0];
$salt = #$parts[1];
$testcrypt = JUserHelper::getCryptedPassword($credentials['password'], $salt);
if ($crypt == $testcrypt) {
$user = JUser::getInstance($result->id); // Bring this in line with the rest of the system
$response->email = $user->email;
$response->fullname = $user->name;
if (JFactory::getApplication()->isAdmin()) {
$response->language = $user->getParam('admin_language');
}
else {
$response->language = $user->getParam('language');
}
$response->status = JAuthentication::STATUS_SUCCESS;
$response->error_message = '';
} else {
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message = JText::_('JGLOBAL_AUTH_INVALID_PASS');
}
} else {
$response->status = JAuthentication::STATUS_FAILURE;
$response->error_message = JText::_('JGLOBAL_AUTH_NO_USER');
}
}

Categories