This topic is locked
[SOLVED]

 Password Rotation

1/19/2014 4:32:04 PM
PHPRunner General questions
S
Stucco author

Hi,
I am looking if anyone has found a way to enable password rotation / expiration. For example, a password expires every 60 days. A user that logs in with an expired password would not be able to perform actions in the system until their password has been updated (possibly always just redirect actions to the password reset page).
Thanks!

Admin 1/20/2014

Here is how this can be done

  1. You are going to have one more field in the login table name PasswordLastChanged (datetime).
  2. AfterAppInit event - check the following conditions

  • user is logged in
  • last password change was more than 60 days ago
  • current page URL is not changepwd.php
    If all of above is true redirect user to changepwd.php. Optionally display a message why password needs to be changed.

  1. AfterChangePassword event - update PasswordLastChanged field with the current date.

S
Stucco author 2/22/2014

Hi,
I have worked through this, but have a few PHPRunner specific questions.



//Set password rotation interval

$password_change_interval = 60;
//Need better way to check if a user is logged in

if(isset($_SESSION["UserID"])){

$password_expired = true;

if($data["last_password_change"] != ""){

$lpc = new DateTime($_SESSION["user"]["last_password_change"]);

$now = new DateTime();

$diff = ($now->getTimestamp() - $lpc->getTimestamp()) / (24 * 60 * 60);

if($diff < $password_change_interval){

$password_expired = false;

}

}
if($password_expired){

//Need to check if on changepwd.php

header("Location: changepwd.php");

exit();

}

}


First, I think there is a better way to check if there is a user logged in, because the session variable is still populated after logout, but I am not able to find it.
Second, I need to check that the current page url is not changepwd.php, however, I am not sure what variable I am able to access inside AfterAppInit to do this.
Thank you!

Admin 2/22/2014

Session is destroyed during logout process so no session variable is populated after logout.
Here is the answer to your second question:

http://webcheatsheet.com/php/get_current_page_url.php

S
Stucco author 3/1/2014

Hi,
One more question. How can I easily display the message using the existing $message display built into the changepwd page?
I am redirecting there, but I'm not sure how to redirect and fill the message variable.
Thanks!!!

Admin 3/1/2014

Use BeforeDisplay event of change password page:

$xt->assign("message", "my message");
S
Stucco author 3/16/2014

Hi All,
Just came back to record what I did as the final solution.
First - Turn on Log login/logout actions to the database in the Security > Locking and Audit options.
Second - Record the last password changed date in the session by adding the following to the Login Page > After Successful Login event



$_SESSION["last_password_change"] = getLastPasswordChange($conn, $username);


Third - Calculate against the last password change to ensure it is less than 60 days by adding this code to the After Application Initialized event.



function getLastPasswordChange($conn, $username){

$str = "SELECT MAX(`datetime`) as last_password_change FROM `audit` WHERE '".$username."' = `audit`.`user` AND `audit`.`action` = 'change password';";

$rs = db_query($str,$conn);

while($row = db_fetch_array($rs)) {

return $row["last_password_change"];

}

return "";

}
function curPageName() {

return substr($_SERVER["SCRIPT_NAME"],strrpos($_SERVER["SCRIPT_NAME"],"/")+1);

}
//Set password rotation interval

$password_change_interval = 60;
//If a user is logged in

if(isset($_SESSION["UserID"])) {

// Check if the last password change was more than X days ago.

$password_expired = true;

if($_SESSION["last_password_change"] == ""){

$password_expired = false;

}

if($password_expired) {

$lpc = new DateTime($_SESSION["last_password_change"]);

$now = new DateTime();

$diff = ($now->getTimestamp() - $lpc->getTimestamp()) / (24 * 60 * 60);

//echo $now->format('Y-m-d H:i:s') . " - " . $lpc->format('Y-m-d H:i:s') . " " . $diff;

if($diff < $password_change_interval) {

$password_expired = false;

}

}
if($password_expired){

if(curPageName() != "changepwd.php") {

header("Location: changepwd.php?expired=true");

exit();

}

}

}


Fourth, update the session variable on change by adding this code to the Change Password Page > After password changed event



$_SESSION["last_password_change"] = date_format(new DateTime(),"Y-m-d H:i:s");


Fifth, give a message to the user letting them know their password expired by adding this code to the Change Password Page > Before display event. I also added a display of complexity requirements.



//Set the custom message for expiration password change.

$msg = $xt->xt_vars["message"] . "<br /><br />";

if(isset($_GET["expired"])){

$msg .= "Your password has expired.<br /><br />";

}

$msg .= "Your new password must:<br />Be at least 8 characters<br />Contain at least 4 unique characters<br />Contain at least 2 digits or symbols<br />Contain letters in both upper and lower case<br />";

$xt->assign("message", $msg);

$xt->assign("message_block",true);


Sixth (Optional), the Change Password Page successful page is pretty worthless with just a back button, so I replaced it with the back to menu button in the style editor. To do this I had to add the menubutton brick to the bricks.xml file, because it wasn't listed before.

S
stiven 4/7/2014

Hello,
This works great! my approach was a little different but I got it working. Is there any way to force the user not to use the last 3 passwords he used?
Thanks

S
Stucco author 4/7/2014

I don't store the historic passwords, but I suppose you could. You may want to look at using a table besides the audit table to support the change process, and then inserting each password into it as it is changed.