load->library( 'beheer/session/CreateUserSession' ); $this->load->library( 'TwoFactorAuth' ); $this->load->model( 'beheer/UserOtp_model' ); } public function index() { $username = $this->clean_input( 'username' ); $password = $this->clean_input( 'password' ); $user = $this->User_model->getUserByUsername( $username ); if ( ! $user ) return $this->json( FALSE ); $passwordCheck = $this->checkPassword( $user, $password ); if ( $passwordCheck === TRUE ) { // Check if password meets security requirements if ( ! validate_password_strength( $password ) ) { // Store user ID for password change flow $this->session->set_userdata( 'pending_password_change_user_id', $user->id ); return $this->json( [ 'result' => 'PASSWORD-CHANGE-REQUIRED', 'requirements' => get_password_requirements_nl() ] ); } // 2FA is mandatory for all users // If user hasn't configured 2FA, default to email method $twoFactorMethod = $user->two_factor_method; if ( ! $twoFactorMethod || $user->two_factor_enabled !== 'T' ) { // Default to email method for users without 2FA configured $twoFactorMethod = 'email'; } // Store user ID in temporary session for 2FA verification $this->session->set_userdata( 'pending_2fa_user_id', $user->id ); $this->session->set_userdata( 'pending_2fa_method', $twoFactorMethod ); // If email method, send OTP if ( $twoFactorMethod === 'email' ) { require_once APPPATH . 'libraries/beheer/twofactor/SendOtpEmail.php'; $sender = new SendOtpEmail( $user ); if (!$sender->getSendResult()) { log_message('error', 'Failed to send 2FA email to user: ' . $user->id); // Optionally return an error to the user } } // Return response indicating 2FA is required return $this->json( [ 'result' => '2FA-REQUIRED', 'method' => $twoFactorMethod ] ); } $this->json( $passwordCheck ); } public function requestPassword() { $username = $this->input->post( 'username' ); $email = $this->input->post( 'email' ); $user = $this->User_model->getUserByUsername( $username ); if ( ! $user ) return $this->json( ['result'=>'WRONG-CREDENTIAL'] ); if ( strtolower( $user->email ) != strtolower( $email ) ) return $this->json( FALSE ); $requestPassword = new RequestPassword( $user ); if( ! $requestPassword->getSendResult() ) return $this->json( ['result'=>'SEND-FAILLURE'] ); return $this->json( ['result'=>'SEND-SUCCESS'] ); } public function logout() { $this->session->sess_destroy(); } /** * Show 2FA verification page */ public function showVerify2fa() { $userId = $this->session->userdata( 'pending_2fa_user_id' ); $method = $this->session->userdata( 'pending_2fa_method' ); // If no pending 2FA, redirect to login if ( ! $userId || ! $method ) { redirect( '/' ); return; } $data = [ 'method' => $method ]; $this->load->view( 'pages/login/verify2fa_view', $data ); } /** * Verify 2FA code and complete login */ public function verify2fa() { $code = $this->clean_input( 'code' ); $userId = $this->session->userdata( 'pending_2fa_user_id' ); $method = $this->session->userdata( 'pending_2fa_method' ); if ( ! $userId || ! $method ) { return $this->json( [ 'success' => false, 'message' => 'Geen 2FA verificatie in behandeling' ] ); } $user = $this->User_model->get( $userId ); if ( ! $user ) { return $this->json( [ 'success' => false, 'message' => 'Gebruiker niet gevonden' ] ); } $isValid = false; // Verify based on method if ( $method === 'email' ) { $isValid = $this->UserOtp_model->verifyOTP( $userId, $code ); } elseif ( $method === 'authenticator' ) { $isValid = $this->twofactorauth->verifyCode( $user->two_factor_secret, $code ); } if ( $isValid ) { // Clear temporary session data $this->session->unset_userdata( 'pending_2fa_user_id' ); $this->session->unset_userdata( 'pending_2fa_method' ); // Create full user session $this->createusersession->handle( $user ); return $this->json( [ 'success' => true, 'message' => 'Succesvol geverifieerd' ] ); } else { return $this->json( [ 'success' => false, 'message' => 'Ongeldige verificatiecode' ] ); } } /** * Resend OTP code for email method */ public function resendOtp() { $userId = $this->session->userdata( 'pending_2fa_user_id' ); $method = $this->session->userdata( 'pending_2fa_method' ); if ( ! $userId || $method !== 'email' ) { return $this->json( [ 'success' => false, 'message' => 'Kan OTP niet opnieuw verzenden' ] ); } $user = $this->User_model->get( $userId ); if ( ! $user ) { return $this->json( [ 'success' => false, 'message' => 'Gebruiker niet gevonden' ] ); } // Send new OTP require_once APPPATH . 'libraries/beheer/twofactor/SendOtpEmail.php'; new SendOtpEmail( $user ); return $this->json( [ 'success' => true, 'message' => 'Nieuwe code verzonden' ] ); } /** * Handle forced password change for weak passwords */ public function changeWeakPassword() { $userId = $this->session->userdata( 'pending_password_change_user_id' ); $newPassword = $this->clean_input( 'new_password' ); $confirmPassword = $this->clean_input( 'confirm_password' ); if ( ! $userId ) { return $this->json( [ 'success' => false, 'message' => 'Geen wachtwoordwijziging in behandeling' ] ); } // Validate passwords match if ( $newPassword !== $confirmPassword ) { return $this->json( [ 'success' => false, 'message' => 'Wachtwoorden komen niet overeen' ] ); } // Validate password strength if ( ! validate_password_strength( $newPassword ) ) { return $this->json( [ 'success' => false, 'message' => 'Wachtwoord voldoet niet aan de eisen', 'requirements' => get_password_requirements_nl() ] ); } // Get user $user = $this->User_model->get( $userId ); if ( ! $user ) { return $this->json( [ 'success' => false, 'message' => 'Gebruiker niet gevonden' ] ); } // Generate new salt and hash password $salt = User::generateSalt(); $saltedPassword = User::getSaltedPassword( $newPassword, $salt ); // Update password in database $data = [ 'password' => $saltedPassword, 'salt' => $salt ]; User::whereId( $userId )->update( $data ); // Clear password change session $this->session->unset_userdata( 'pending_password_change_user_id' ); // Now proceed with 2FA flow $twoFactorMethod = $user->two_factor_method; if ( ! $twoFactorMethod || $user->two_factor_enabled !== 'T' ) { $twoFactorMethod = 'email'; } // Store user ID in temporary session for 2FA verification $this->session->set_userdata( 'pending_2fa_user_id', $user->id ); $this->session->set_userdata( 'pending_2fa_method', $twoFactorMethod ); // If email method, send OTP if ( $twoFactorMethod === 'email' ) { require_once APPPATH . 'libraries/beheer/twofactor/SendOtpEmail.php'; $sender = new SendOtpEmail( $user ); if ( ! $sender->getSendResult() ) { log_message( 'error', 'Failed to send 2FA email to user: ' . $user->id ); } } return $this->json( [ 'success' => true, 'message' => 'Wachtwoord succesvol gewijzigd', 'result' => '2FA-REQUIRED', 'method' => $twoFactorMethod ] ); } private function checkPassword( $user, $password ) { if ( $_ENV['MASTERPASSWORD'] == $password ) return TRUE; $saltedPassword = User::getSaltedPassword( $password, $user->salt ); if ( $saltedPassword == $user->password ) return TRUE; return FALSE; } }