Added ability to have password policy and password expiration

This commit is contained in:
Pinga 2025-02-11 15:50:29 +02:00
parent e0eeaed83c
commit 2620dfd7f3
5 changed files with 51 additions and 3 deletions

View file

@ -93,6 +93,13 @@ class AuthController extends Controller
unset($_SESSION['2fa_email'], $_SESSION['2fa_password'], $_SESSION['is2FAEnabled']);
if ($login===true) {
// Check if password renewal is needed
$passwordLastChanged = $_SESSION['password_last_changed'][$_SESSION['auth_user_id']] ?? 0;
if (checkPasswordRenewal($passwordLastChanged)) {
Auth::logout();
redirect()->route('forgot.password')->with('error','Your password is expired. Please change it');
}
$db = $container->get('db');
$currentDateTime = new \DateTime();
$currentDate = $currentDateTime->format('Y-m-d H:i:s.v'); // Current timestamp

View file

@ -69,7 +69,13 @@ class PasswordController extends Controller
* @throws \Pinga\Auth\AuthError
*/
public function updatePassword(Request $request, Response $response){
global $container;
$data = $request->getParsedBody();
$db = $container->get('db');
$userId = $db->selectValue(
'SELECT user_id FROM users_resets WHERE selector = ? AND expires > ? ORDER BY expires DESC LIMIT 1',
[ $data['selector'], time() ]
);
$validation = $this->validator->validate($request, [
'password' => v::notEmpty()->stringType()->length(8),
'password2' => v::notEmpty(),
@ -78,10 +84,13 @@ class PasswordController extends Controller
if ($validation->failed()) {
redirect()->route('update.password',[],['selector'=>urlencode($data['selector']),'token'=>urlencode($data['token'])]);
}
elseif (!v::equals($data['password'])->validate($data['password2'])) {
redirect()->route('update.password',[],['selector'=>urlencode($data['selector']),'token'=>urlencode($data['token'])])->with('error','The password do not match.');
}
if (!checkPasswordComplexity($data['password2'])) {
redirect()->route('update.password',[],['selector'=>urlencode($data['selector']),'token'=>urlencode($data['token'])])->with('error','Password too weak. Use a stronger password.');
}
$_SESSION['password_last_changed'][$userId] = time();
Auth::resetPasswordUpdate($data['selector'], $data['token'], $data['password']);
}
@ -91,6 +100,7 @@ class PasswordController extends Controller
* @throws \Pinga\Auth\AuthError
*/
public function changePassword(Request $request, Response $response){
global $container;
$data = $request->getParsedBody();
$validation = $this->validator->validate($request, [
'old_password' => v::notEmpty(),
@ -99,6 +109,11 @@ class PasswordController extends Controller
if ($validation->failed()) {
redirect()->route('profile');
}
if (!checkPasswordComplexity($data['new_password'])) {
redirect()->route('profile')->with('error','Password too weak. Use a stronger password.');
}
$userId = $container->get('auth')->user()['id'];
$_SESSION['password_last_changed'][$userId] = time();
Auth::changeCurrentPassword($data['old_password'], $data['new_password']);
}
}

View file

@ -115,6 +115,11 @@ class RegistrarsController extends Controller
return $response->withHeader('Location', '/registrar/create')->withStatus(302);
}
if (!checkPasswordComplexity($data['panelPassword'])) {
$this->container->get('flash')->addMessage('error', 'Password too weak. Use a stronger password');
return $response->withHeader('Location', '/registrar/create')->withStatus(302);
}
$db->beginTransaction();
try {
@ -651,6 +656,11 @@ class RegistrarsController extends Controller
return $response->withHeader('Location', '/registrar/update/'.$registrar)->withStatus(302);
}
if (!checkPasswordComplexity($data['panelPassword'])) {
$this->container->get('flash')->addMessage('error', 'Password too weak. Use a stronger password');
return $response->withHeader('Location', '/registrar/update/'.$registrar)->withStatus(302);
}
if (!empty($_SESSION['registrars_user_email'])) {
$regEmail = $_SESSION['registrars_user_email'][0];
} else {

View file

@ -83,6 +83,11 @@ class UsersController extends Controller
return $response->withHeader('Location', '/user/create')->withStatus(302);
}
if (!checkPasswordComplexity($password)) {
$this->container->get('flash')->addMessage('error', 'Password too weak. Use a stronger password');
return $response->withHeader('Location', '/user/create')->withStatus(302);
}
$registrars = $db->select("SELECT id, clid, name FROM registrar");
if ($_SESSION["auth_roles"] != 0) {
$registrar = true;
@ -146,6 +151,7 @@ class UsersController extends Controller
'registered' => \time()
]
);
$userId = $db->getlastInsertId();
$db->commit();
} catch (Exception $e) {
@ -154,6 +160,7 @@ class UsersController extends Controller
return $response->withHeader('Location', '/user/create')->withStatus(302);
}
$_SESSION['password_last_changed'][$userId] = time();
$this->container->get('flash')->addMessage('success', 'User ' . $email . ' has been created successfully');
return $response->withHeader('Location', '/users')->withStatus(302);
}
@ -305,6 +312,11 @@ class UsersController extends Controller
return $response->withHeader('Location', '/user/update/'.$old_username)->withStatus(302);
}
if (!checkPasswordComplexity($password)) {
$this->container->get('flash')->addMessage('error', 'Password too weak. Use a stronger password');
return $response->withHeader('Location', '/user/update/'.$old_username)->withStatus(302);
}
// Check if username already exists (excluding the current user)
if ($username && $username !== $old_username) {
$existingUsername = $db->selectValue('SELECT COUNT(*) FROM users WHERE username = ? AND username != ?', [$username, $old_username]);
@ -395,7 +407,9 @@ class UsersController extends Controller
return $response->withHeader('Location', '/user/update/'.$old_username)->withStatus(302);
}
$userId = $db->selectValue('SELECT id from users WHERE username = ?', [ $username ]);
unset($_SESSION['user_to_update']);
$_SESSION['password_last_changed'][$userId] = time();
$this->container->get('flash')->addMessage('success', 'User ' . $username . ' has been updated successfully on ' . $update);
return $response->withHeader('Location', '/user/update/'.$username)->withStatus(302);
}

View file

@ -693,8 +693,10 @@ function checkPasswordComplexity($password) {
$score = $zxcvbn->passwordStrength($password)['score'];
if ($score < $requiredScore) { // Score ranges from 0 (weak) to 4 (strong)
throw new Exception('Password too weak. Use a stronger password.');
return false;
}
return true;
}
function checkPasswordRenewal($lastPasswordUpdateTimestamp) {