Set random password - cakephp

I'm quite new to phpCake and its principles and would like to know the cleanest solution for my requirement:
I'd like to set a random password when a new user is added.
The new user should receive an email with the password.
I see two possibilities to approach the random password:
1) Set the random password in the controller:
$this->request->data['User']['password'] = 'randomPassword';
The 'randomPassword' could be got by implementing a component.
2) The random password is set in the beforeSave method inside the user model. But how could I access this password from inside the controller then? I would need this to send the password in the email which is done inside my controller.
What is the cleaner solution? Or is there a better approach?

You'd do it on a beforeSave() callback method.
Details here: http://book.cakephp.org/2.0/en/models/callback-methods.html#beforesave
You can detect if they're creating a "new" user, as opposed to updating an existing one, then, if they're new, generate a password. When the user is saved, it will have the password data in it.
// User model
public function beforeSave($options = array()) {
if(!isset($this->data['User']['id'])) {
// generate password here
}
return true;
}
Per the comments on your question, I don't think it's ideal to send the actual password, but - the above answer would work for generating a token or anything else you want to use.

$randomPassword = md5(AuthComponent::user("id));
$this->request->data['User']['password'] = $randomPassword;
This will give you a giant password, you can cut to the first 5-10 chars as u wish.
$randomPassword = $substr($randomPassword, 0,10);

Related

How to create user in database manually in Yii2?

I do import of users from a csv file to the database. In csv file I have some kinda username and password string. So how do I create a new user manually?
As I understand I need to getPasswordHash and generateAuthKey (last one generates random string). But probably I loose something important since when I try to log in I get an error that Username or Password is incorrect. Did anyone ever experienced such situation? Thanks in advance.
This should be the minimum required in your case. $username and $password are raw values taken from the CSV. Remember that there will be validation applied.
$user = new User();
$user->username = $username;
$user->setPassword($password);
$user->generateAuthKey();
return $user->save();
I think you forgot to set an active status of new User. You should check it in Login method of User model in your app, or in actionLogin of SiteController. For example, in my app the login method is:
public function login()
{
if ($this->validate() and $this->getUser()->status !== User::INACTIVE_STATUS) {
return Yii::$app->user->login($this->getUser(), $this->rememberMe ? 3600 * 24 * 30 : 0);
}
return false;
}
If you show your code we can help you faster)
So if you are importing a list of users from a csv file, you will probably process this in a loop, try:
foreach ($csv_data as $user_data) {
$user = new User();
$user->setPassword($password);
$user->username = $user_data->username // or anything else, depending on your code
$user->status = 1 // or = User::STATUS_ACTIVE, depending on your code
$user->save();
}

Phpunit password comparison

I would like to test a login function that one of the developers produced. What I would like to do is have test-users be created in my setUp and then I would like to use these users to test the login function. I would like to see that it returns the correct boolean when username and password are equal to the ones stored in our database. My problem is that when I am inserting my users at the moment I am giving the passwords in plain-text hence they are being stored in the database in plain-text, however there is an issue here. The login function hashes the password as you are trying to log in as the passwords in the database are hashed when registration is done. So basically the plain-text password I just inserted will never be matched since the login function hashes the password in an attempt to find a match. So what I would need to do is hash the test-user's password as I insert it. How would I go about doing this? This is what my code looks like at the moment:
<?php
include 'functions.php';
class Test extends PHPUnit_Framework_TestCase {
protected function setUp(){
global $mysqli;
$mysqli = new mysqli('localhost', 'xxx', 'xxxxx', 'xxxxx');
$mysqli->query("INSERT INTO members (id, username, pnumber, password) VALUES ('200', 'testbrute', '920314', 'xxxxx')");
}
public function testLogin(){
global $mysqli;
$correctPass = Login('920314','xxxxxx', $mysqli);
$this->assertTrue($correctPass);
$wrongPass = Login('920314','xxxxxxxxx', $mysqli);
$this->assertFalse($wrongPass);
$NoUserExists = Login("980611-5298","--..--..--", $mysqli);
$this->assertFalse($NoUserExists);
}
protected function tearDown(){
$mysqli = new mysqli('localhost', 'xxx', 'xxxxx', 'xxxxx');
$mysqli->query("DELETE FROM members WHERE id IN (200)");
}
}
?>
This is what the login function looks like:
function login($pnumber, $password, $mysqli) {
// Using prepared Statements means that SQL injection is not possible.
if ($stmt = $mysqli->prepare("SELECT id, username, password, salt FROM members WHERE pnumber = ? LIMIT 1")) {
$stmt->bind_param('s', $pnumber); // Bind "$pnumber" to parameter.
$stmt->execute(); // Execute the prepared query.
$stmt->store_result();
$stmt->bind_result($user_id, $username, $db_password, $salt); // get variables from result.
$stmt->fetch();
$password = hash('sha512', $password.$salt); // hash the password with the unique salt.
if($stmt->num_rows == 1) { // If the user exists
// We check if the account is locked from too many login attempts
if(checkbrute($user_id, $mysqli) == true) {
// Account is locked
// Send an email to user saying their account is locked
return "account locked";
} else {
if($db_password == $password) { // Check if the password in the database matches the password the user submitted.
// Password is correct!
$ip_address = $_SERVER['REMOTE_ADDR']; // Get the IP address of the user.
$user_browser = $_SERVER['HTTP_USER_AGENT']; // Get the user-agent string of the user.
$user_id = preg_replace("/[^0-9]+/", "", $user_id); // XSS protection as we might print this value
$_SESSION['user_id'] = $user_id;
$username = preg_replace("/[^a-zA-Z0-9_\-]+/", "", $username); // XSS protection as we might print this value
$_SESSION['username'] = $username;
$_SESSION['login_string'] = hash('sha512', $password.$ip_address.$user_browser);
// Login successful.
return "login successful";
} else {
// Password is not correct
// We record this attempt in the database
$now = time();
$mysqli->query("INSERT INTO login_attempts (user_id, time) VALUES ('$user_id', '$now')");
return 'pass incorrect';
}
}
} else {
// No user exists.
return 'no exist';
}
}
}
I am new to phpunit and testing in general so please be overly-descriptive.
Forget trying to test against the actual database. As a general rule, you don't want to have your tests dependent on external services if you can help it.
You can inject a mock mysqli object and specify it's behavior. Then you don't have to worry about any values being added to the database or are dependent on having the database even exist.
So in your test rather than declaring a global $mysqli do:
$mockMysqli = $this->getMockBuilder('mysqli')
->disableOriginalConstructor()
->setMethods(array('prepare'))
->getMock();
$mockMysqli->expects($this->once())
->method('prepare')
->will($this->returnValue($mockStmt) //Have to also create a mock mysqli_stmt object
Based on how your function is, you will end up with a few mock objects returning other mock objects which is a code smell that you function is doing too much. Because of this, you would be better off breaking it up into smaller pieces that can then be mocked and tested separately. I find that generally speaking if the function is hard to test, that it is not a good design and should be refactored. Most good designs end up being easy to test with one or two mock objects.

Create encrypted passwords

I am using a small cakephp setup, with no forgot password functionality. I want to be able to create a hashed password, using the same security hashing method and cipherseed used in the site.
Is there a way to recreate the setup in a local php file which would output a hashed password, the system would understand?
Make sure to specify that you're using the Security Component in whatever controller you're working in:
var $components = array('Security');
Then, in the action (method/function...whatever):
$myPassword = 'pizzaRules!';
$hashedPassword = Security::hash($myPassword, null, true);
The true at the end says you want to use the site's salt.

Hashing a password

I have built a login form but not a sign up form so i am putting the users details directly into the sql database.
I have found out that cakephp automatically hashes the password when the user tries to login, but at the moment I cant login because the password in the database is not hashed.
how does cakephp hash the passwords?
My security salt is Dhhfei38fhDg37dg6Dg208Dh3h380Hrjd3
Could you please walk me through what it does?
Hashed passwords in cakephp are created by:
$hashedPasswords = Security::hash($yourPass, NULL, true);
Check the cakephp manual for more info
debug(AuthComponent::password("your-password"));
That's if you are hashing your password this way inside your UserModel.
public function beforeSave() {
if (isset($this->data[$this->alias]['password'])) {
$this->data[$this->alias]['password'] = AuthComponent::password($this->data[$this->alias]['password']);
}
return true;
}
http://book.cakephp.org/2.0/en/core-libraries/components/authentication.html#hashing-passwords
Add a new user with a password. You can take the hash value of the new user's password and paste it into other user's records.
As of Cakephp 2.0, Cake only hashes passwords in the login process,
on other places (like register-method...), the password won't be hashed automatically, that's because it was considered a strange behaviour to people who where new to cakephp.
If you want to hash the password, you need to use the method Sudhir mentioned.
One of the advantages that cake does not hash passwords automatically anymore is, that you can more easily check the password complexity ( if there are included special characters, numbers, letters ecc).
According to How to – password hashing in cakephp: "Security::hash takes the type sha1."

cakephp sha1 password saving in mysql

I have forgot password feature in my cakephp application. The function for this will request the email address, find this user, generate a new password, convert it to sha1 and save it to the database, emailing the contents to the user.
Anyway I am having issues, the generated sha1 password is different to the one being saved.
I have called the info to the screen to show what is happening:
TEMP PASSWORD- lHQcVp4 (FROM THE FUNCTION)
Blockquote
SHA1 PASSWORD- 0ee4ae757733f458b9e395a8457c2ef307af99f0 (FROM sha1($user['User']['tmp_password']);
Auth Password PASSWORD- 93df9bd251620d0634235c22f4ab6fe9ad5421f4 (FROM: $this->Auth->password($user['User']['tmp_password']);)
DB Record After Save PASSWORD- 13ef648db45cc62b593c3943646806af06846016 (FROM $this->User->field('password');)
I am saving the data as follows: $this->User->save($user, false)
Why would it come though differently all 3 times? I cannot work it out. Very strange.
Thankyou
sha1($user['User']['tmp_password']
This will simply hash the password and output the text
$this->Auth->password($user['User']['tmp_password']);
This hashes the password with the cakephp salt defined in core.php. This is why you see a difference
If you simply set the password value to $user['User']['password'] and call save() on it, Auth might be hashing the password again since it doesn't know you've already hashed it. Have you tried just setting the password to $user['User']['password'] and calling save() on it? Let Auth handle the hashing for you.

Resources