CIM67 - Block Users after 5 failed login attempts

This commit is contained in:
“VeLiTi”
2024-04-16 11:03:00 +02:00
parent aebeb88b68
commit 32965b319f
9 changed files with 91 additions and 42 deletions

View File

@@ -9,9 +9,13 @@ $user_credentials = json_decode(decode_payload($input),true);
$pdo = dbConnect($dbname);
$username = $user_credentials['username'] ?? '';
//Define Query
$stmt = $pdo->prepare('SELECT id, username, password, salesID, partnerhierarchy, view, service, settings, lastlogin, userkey, language FROM users WHERE username = ?');
$stmt = $pdo->prepare('SELECT * FROM users WHERE username = ?');
//Excute Query
$stmt->execute([$username]);
//SETUP SQL FOR LOGIN_COUNT
$sql_login = 'UPDATE users SET login_count = ? WHERE id = ?';
// Check if username exists. Verify user exists then verify
if ($stmt->rowCount() == 1) {
$user_data = $stmt->fetch();
@@ -19,47 +23,71 @@ if ($stmt->rowCount() == 1) {
$profile = getProfile($user_data['settings'],$permission);
$password = $user_credentials['password'];
if (array_key_exists('resetkey', $user_credentials)){
if ($user_credentials['resetkey'] == ''){
//Reset procedure
//STEP 1.A- Create resetkey
$headers = array('alg'=>'HS256','typ'=>'JWT');
$payload = array('username'=>$user_data['username'], 'exp'=>(time() + 1800));
$resetkey = generate_jwt($headers, $payload);
//STEP 1.B Store in DB
$sql = 'UPDATE users SET resetkey = ? WHERE id = ?';
$stmt = $pdo->prepare($sql);
$stmt->execute([$resetkey,$user_data['id']]);
//STEP 2- Send to user
include_once './assets/mail/email_template_reset.php';
send_mail($user_data['username'],$subject,$message,'','');
}
if ($user_data['login_count'] < 5){
if (array_key_exists('resetkey', $user_credentials)){
if ($user_credentials['resetkey'] == ''){
//Reset procedure
//STEP 1.A- Create resetkey
$headers = array('alg'=>'HS256','typ'=>'JWT');
$payload = array('username'=>$user_data['username'], 'exp'=>(time() + 1800));
$resetkey = generate_jwt($headers, $payload);
//STEP 1.B Store in DB
$sql = 'UPDATE users SET resetkey = ? WHERE id = ?';
$stmt = $pdo->prepare($sql);
$stmt->execute([$resetkey,$user_data['id']]);
//STEP 2- Send to user
include_once './assets/mail/email_template_reset.php';
send_mail($user_data['email'],$subject,$message,'','');
//STEP 3- Update Login count
$login_attempt = $user_data['login_count'] + 1;
$stmt_login = $pdo->prepare($sql_login);
$stmt_login->execute([$login_attempt, $user_data['id']]);
}
} else { //STANDARD LOGIN
if (password_verify($password, $user_data['password'])) {
$token = createCommunicationToken($user_data['service']);
} else { //STANDARD LOGIN
if (password_verify($password, $user_data['password'])) {
$token = createCommunicationToken($user_data['service']);
$user = array(
'id' => $user_data['id'],
'username' => $user_data['username'],
'salesID' => $user_data['salesID'],
'partnerhierarchy' => $user_data['partnerhierarchy'],
'permission' => $permission,
'profile' => $profile,
'service' => $user_data['service'],
'userkey' => $user_data['userkey'],
'language' => $user_data['language'],
'token' => $token
);
//Encrypt results
$messages = generate_payload($user);
//Send results
print_r($messages);
} else {
http_response_code(403); //Not authorized
$user = array(
'id' => $user_data['id'],
'username' => $user_data['username'],
'salesID' => $user_data['salesID'],
'partnerhierarchy' => $user_data['partnerhierarchy'],
'permission' => $permission,
'profile' => $profile,
'service' => $user_data['service'],
'userkey' => $user_data['userkey'],
'language' => $user_data['language'],
'token' => $token
);
//Reset login count after succesfull attempt
$login_attempt = 0;
$stmt_login = $pdo->prepare($sql_login);
$stmt_login->execute([$login_attempt, $user_data['id']]);
//Encrypt results
$messages = generate_payload($user);
//Send results
print_r($messages);
} else {
//Update Login count with failed attempt
$login_attempt = $user_data['login_count'] + 1;
$stmt_login = $pdo->prepare($sql_login);
$stmt_login->execute([$login_attempt, $user_data['id']]);
//Send Response
http_response_code(403); //Not authorized
}
}
}
} else {
//User is blocked & send error
$messages = generate_payload('1');
//------------------------------------------
//Send results
//------------------------------------------
echo $messages;
}
} elseif (array_key_exists('resetkey', $user_credentials)) {
if ($user_credentials['resetkey'] != ''){
//UPDATE PASSWORD BASED ON RESETKEY
@@ -67,6 +95,8 @@ if ($stmt->rowCount() == 1) {
$passwordvalid = password_hash($password, PASSWORD_DEFAULT);
$stmt = $pdo->prepare('UPDATE users SET password = ? WHERE resetkey = ? ');
$stmt->execute([$passwordvalid, $user_credentials['resetkey']]);
//
} else {
http_response_code(403);//Not authorized
}

View File

@@ -68,7 +68,7 @@ if(isset($criterias['totals']) && $criterias['totals'] ==''){
}
else {
//SQL for Paging
$sql = 'SELECT id,username,salesID, partnerhierarchy, view, created, service, settings, lastlogin, userkey, language FROM users '.$whereclause.' ORDER BY lastlogin DESC LIMIT :page,:num_products';
$sql = 'SELECT id,username, email, salesID, partnerhierarchy, view, created, service, settings, lastlogin, userkey, language,login_count FROM users '.$whereclause.' ORDER BY lastlogin DESC LIMIT :page,:num_products';
}
$stmt = $pdo->prepare($sql);

View File

@@ -369,6 +369,8 @@ async function closePort(){
}
maintenanceRun = 0; // reset maintenanceRun
// Refresh the page
location.reload();
}
async function updateHistory(){

View File

@@ -50,6 +50,8 @@ if ($_SERVER['REQUEST_METHOD'] === 'POST') {
if ($responses === 'NOK'){
$retry++;
$password_err = 'Not authorized, please retry';
} elseif ($responses == 1){
$password_err = 'Too many login attempts. User blocked, please contact your administrator';
} else {
// Start a new session
session_start();

View File

@@ -16,6 +16,7 @@ $create_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],
$user = [
'id' => '',
'username' => '',
'email' => '',
'partnerhierarchy' => '',
'view' => 3,
'service' => 0,
@@ -103,6 +104,8 @@ $view .= '<div class="content-block tab-content active">
<input type="text" name="" placeholder="" value="'.(($user['userkey']!='') ? $enabled : $disabled ).'" readonly>
<label for="username">'.$User_username.'</label>
<input id="name" type="email" name="" placeholder="'.$User_username.'" value="'.$user['username'].'" readonly">
<label for="username">'.$User_email.'</label>
<input id="name" type="email" name="" placeholder="'.$User_email.'" value="'.$user['email'].'" required">
<label for="view">'.$User_permission.'</label>
<input type="text" name="" placeholder="" value="'.${'permission'.$user['view']}.'" readonly>
<label for="profile">'.$User_profile.'</label>

View File

@@ -263,12 +263,15 @@ $users_search = 'Zoek gebruiker';
$User_service = 'Service';
$User_update = 'Actief';
$User_username = 'Gebruikersnaam';
$User_email = 'Email';
$User_partnerhierarchy = 'Hierarchy';
$User_permission = 'Toestemming';
$User_profile = 'Profiel';
$User_lastlogin = 'Laatste inlog';
$User_language = 'Taal';
$User_pw_reset = 'Password reset';
$User_pw_login_count = 'Mislukte inlog pogingen';
$User_block = 'Geblokkeerd';
$reset_message = 'Password reset started => See your email inbox for further instructions, you will be redirected to the login page.';

View File

@@ -263,12 +263,15 @@ $users_search = 'Search user';
$User_service = 'Service';
$User_update = 'Active';
$User_username = 'Username';
$User_email = 'Email';
$User_partnerhierarchy = 'Hierarchy';
$User_permission = 'Permission';
$User_profile = 'Profile';
$User_lastlogin = 'Lastlogin';
$User_language = 'Language';
$User_pw_reset = 'Password reset';
$User_pw_login_count = 'Failed login attempts';
$User_block = 'Blocked';
$reset_message = 'Password reset started => See your email inbox for further instructions, you will be redirected to the login page.';

View File

@@ -16,6 +16,7 @@ $create_allowed = isAllowed($page ,$_SESSION['profile'],$_SESSION['permission'],
$user = [
'id' => '',
'username' => '',
'email' => '',
'partnerhierarchy' => '',
'view' => 3,
'service' => 0,
@@ -23,7 +24,8 @@ $user = [
'userkey' => 1,
'created' => '',
'lastlogin' => '',
'language' => 'US'
'language' => 'US',
'login_count' => 0
];
$user_ID = $_GET['id'] ?? '';
@@ -174,6 +176,8 @@ $view .= '<div class="content-block tab-content active">
</select>
<label for="username">'.$User_username.'</label>
<input id="name" type="email" name="username" placeholder="'.$User_username.'" value="'.$user['username'].'" required">
<label for="username">'.$User_email.'</label>
<input id="name" type="email" name="email" placeholder="'.$User_email.'" value="'.$user['email'].'" required">
<label for="view">'.$User_permission.'</label>
<select id="view" name="view" required>
<option value="3" '.($user['view']==3?' selected':'').'>'.$permission3.'</option>
@@ -267,6 +271,8 @@ $view .= '<div class="content-block tab-content">
<input id="name" type="text" name="" placeholder="'.$general_created.'" value="'.$user['created'].'" readonly>
<label for="">'.$User_lastlogin.'</label>
<input id="name" type="text" name="" placeholder="'.$User_lastlogin.'" value="'.$user['lastlogin'].'" readonly>
<label for="">'.$User_pw_login_count.'</label>
<input id="name" type="text" name="" placeholder="'.$User_pw_login_count.'" value="'.$user['login_count'].'" readonly>
</div>
</div>';

View File

@@ -135,7 +135,7 @@ $view .= '
$permission_user = 'permission'.$response->view;
$view .= '
<tr>
<td class="responsive-hidden"></td>
<td class="responsive-hidden">'.(($response->login_count > 4)? '<span class="status disabled">'.$User_block:'').'</td>
<td class="responsive-hidden">'.(($response->userkey && $response->userkey !='')? '<span class="status enabled">'.$enabled:'<span class="status">'.$disabled).'</td>
<td class="responsive-hidden">'.(($response->service && $response->service !='')? '<span class="status enabled">'.$enabled:'<span class="status">'.$disabled).'</td>
<td>'.$response->username.'</td>