Changeset 3390737
- Timestamp:
- 11/05/2025 10:41:15 PM (4 months ago)
- Location:
- keyless-auth
- Files:
-
- 71 added
- 3 edited
-
tags/3.2.2 (added)
-
tags/3.2.2/LICENSE (added)
-
tags/3.2.2/assets (added)
-
tags/3.2.2/assets/css (added)
-
tags/3.2.2/assets/css/2fa-frontend.css (added)
-
tags/3.2.2/assets/css/admin-style.css (added)
-
tags/3.2.2/assets/css/forms-enhanced-dark.css (added)
-
tags/3.2.2/assets/css/forms-enhanced-light.css (added)
-
tags/3.2.2/assets/css/forms-enhanced.css (added)
-
tags/3.2.2/assets/css/help-page.css (added)
-
tags/3.2.2/assets/css/style-back-end.css (added)
-
tags/3.2.2/assets/css/style-front-end.css (added)
-
tags/3.2.2/assets/css/woocommerce-integration.css (added)
-
tags/3.2.2/assets/js (added)
-
tags/3.2.2/assets/js/2fa-frontend.js (added)
-
tags/3.2.2/assets/js/admin-script.js (added)
-
tags/3.2.2/assets/js/help-page.js (added)
-
tags/3.2.2/assets/js/qrcode.js (added)
-
tags/3.2.2/assets/js/qrcode.min.js (added)
-
tags/3.2.2/assets/js/woocommerce-integration.js (added)
-
tags/3.2.2/assets/logo_150_150.png (added)
-
tags/3.2.2/autoload.php (added)
-
tags/3.2.2/includes (added)
-
tags/3.2.2/includes/Admin (added)
-
tags/3.2.2/includes/Admin/Admin.php (added)
-
tags/3.2.2/includes/Admin/Admin.php.backup (added)
-
tags/3.2.2/includes/Admin/Ajax (added)
-
tags/3.2.2/includes/Admin/Ajax/TwoFAAjaxHandler.php (added)
-
tags/3.2.2/includes/Admin/Ajax/index.php (added)
-
tags/3.2.2/includes/Admin/Assets (added)
-
tags/3.2.2/includes/Admin/Assets/AssetLoader.php (added)
-
tags/3.2.2/includes/Admin/Assets/index.php (added)
-
tags/3.2.2/includes/Admin/MenuManager.php (added)
-
tags/3.2.2/includes/Admin/Pages (added)
-
tags/3.2.2/includes/Admin/Pages/DashboardPage.php (added)
-
tags/3.2.2/includes/Admin/Pages/HelpPage.php (added)
-
tags/3.2.2/includes/Admin/Pages/MailLogsPage.php (added)
-
tags/3.2.2/includes/Admin/Pages/OptionsPage.php (added)
-
tags/3.2.2/includes/Admin/Pages/SmtpPage.php (added)
-
tags/3.2.2/includes/Admin/Pages/TemplatesPage.php (added)
-
tags/3.2.2/includes/Admin/Pages/TwoFAUsersPage.php (added)
-
tags/3.2.2/includes/Admin/Pages/index.php (added)
-
tags/3.2.2/includes/Admin/Settings (added)
-
tags/3.2.2/includes/Admin/Settings/SettingsManager.php (added)
-
tags/3.2.2/includes/Admin/Settings/index.php (added)
-
tags/3.2.2/includes/Admin/index.php (added)
-
tags/3.2.2/includes/Core (added)
-
tags/3.2.2/includes/Core/Core.php (added)
-
tags/3.2.2/includes/Core/Database.php (added)
-
tags/3.2.2/includes/Core/Main.php (added)
-
tags/3.2.2/includes/Core/Notices.php (added)
-
tags/3.2.2/includes/Core/PasswordReset.php (added)
-
tags/3.2.2/includes/Core/WooCommerce.php (added)
-
tags/3.2.2/includes/Core/index.php (added)
-
tags/3.2.2/includes/Email (added)
-
tags/3.2.2/includes/Email/MailLogger.php (added)
-
tags/3.2.2/includes/Email/SMTP.php (added)
-
tags/3.2.2/includes/Email/Templates.php (added)
-
tags/3.2.2/includes/Email/index.php (added)
-
tags/3.2.2/includes/Security (added)
-
tags/3.2.2/includes/Security/TwoFA (added)
-
tags/3.2.2/includes/Security/TwoFA/Core.php (added)
-
tags/3.2.2/includes/Security/TwoFA/Frontend.php (added)
-
tags/3.2.2/includes/Security/TwoFA/TOTP.php (added)
-
tags/3.2.2/includes/Security/TwoFA/index.php (added)
-
tags/3.2.2/includes/Security/index.php (added)
-
tags/3.2.2/includes/index.php (added)
-
tags/3.2.2/keyless-auth.php (added)
-
tags/3.2.2/languages (added)
-
tags/3.2.2/languages/keyless-auth.pot (added)
-
tags/3.2.2/readme.txt (added)
-
trunk/includes/Core/Core.php (modified) (5 diffs)
-
trunk/keyless-auth.php (modified) (1 diff)
-
trunk/readme.txt (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
keyless-auth/trunk/includes/Core/Core.php
r3386610 r3390737 48 48 // Hook early to catch wp-login.php requests for redirect 49 49 add_action('init', array($this, 'chrmrtns_kla_maybe_redirect_wp_login'), 1); 50 51 // Hook into failed login to redirect with error parameters 52 add_action('wp_login_failed', array($this, 'handle_failed_login'), 10, 2); 50 53 51 54 // Disable XML-RPC if option is enabled … … 129 132 echo '<p class="chrmrtns-box chrmrtns-error" role="alert" aria-live="assertive">' . wp_kses_post(apply_filters('chrmrtns_kla_admin_approval_error', __('Your account needs to be approved by an admin before you can log-in.', 'keyless-auth'))) . '</p>'; 130 133 } 131 134 135 // Show WordPress native login errors (from wp-login.php redirects) 136 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- URL parameters for error display 137 $login_error = isset($_GET['login_error']) ? sanitize_text_field(wp_unslash($_GET['login_error'])) : ''; 138 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- URL parameters for error display 139 $login_status = isset($_GET['login']) ? sanitize_text_field(wp_unslash($_GET['login'])) : ''; 140 141 if ($login_error || $login_status) { 142 $error_message = $this->get_login_error_message($login_error, $login_status); 143 if ($error_message) { 144 echo '<p class="chrmrtns-box chrmrtns-error" role="alert">' . wp_kses_post($error_message) . '</p>'; 145 } 146 } 147 132 148 // Render the login form 133 149 $this->render_login_form_html($atts); … … 230 246 } elseif (is_wp_error($sent_link)) { 231 247 echo '<p class="chrmrtns-box chrmrtns-error">' . wp_kses_post(apply_filters('chrmrtns_kla_error_send_link_msg', __('Email could not be sent. Please try again.', 'keyless-auth'))) . '</p>'; 248 } 249 250 // Show WordPress native login errors (from wp-login.php redirects) 251 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- URL parameters for error display 252 $login_error = isset($_GET['login_error']) ? sanitize_text_field(wp_unslash($_GET['login_error'])) : ''; 253 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- URL parameters for error display 254 $login_status = isset($_GET['login']) ? sanitize_text_field(wp_unslash($_GET['login'])) : ''; 255 256 if ($login_error || $login_status) { 257 $error_message = $this->get_login_error_message($login_error, $login_status); 258 if ($error_message) { 259 echo '<p class="chrmrtns-box chrmrtns-error" role="alert">' . wp_kses_post($error_message) . '</p>'; 260 } 261 } 262 263 // Show success messages 264 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- URL parameters for success messages 265 if (isset($_GET['loggedout']) && $_GET['loggedout'] === 'true') { 266 echo '<p class="chrmrtns-box chrmrtns-success" role="status">' . esc_html__('You have successfully logged out.', 'keyless-auth') . '</p>'; 267 } 268 269 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- URL parameters for success messages 270 if (isset($_GET['registered']) && $_GET['registered'] === 'true') { 271 echo '<p class="chrmrtns-box chrmrtns-success" role="status">' . esc_html__('Registration complete. Please check your email.', 'keyless-auth') . '</p>'; 272 } 273 274 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- URL parameters for success messages 275 $checkemail = isset($_GET['checkemail']) ? sanitize_text_field(wp_unslash($_GET['checkemail'])) : ''; 276 if ($checkemail === 'confirm') { 277 echo '<p class="chrmrtns-box chrmrtns-success" role="status">' . esc_html__('Check your email for the confirmation link.', 'keyless-auth') . '</p>'; 278 } elseif ($checkemail === 'newpass') { 279 echo '<p class="chrmrtns-box chrmrtns-success" role="status">' . esc_html__('Check your email for your new password.', 'keyless-auth') . '</p>'; 232 280 } 233 281 … … 391 439 392 440 /** 441 * Get user-friendly error message from WordPress login error codes 442 * 443 * @param string $error_code Error code from login redirect. 444 * @param string $login_status Login status parameter. 445 * @return string Human-readable error message. 446 */ 447 private function get_login_error_message($error_code, $login_status) { 448 // Handle common WordPress login error codes 449 $error_messages = array( 450 // Standard wp-login.php error codes 451 'invalid_username' => __('Invalid username or email address.', 'keyless-auth'), 452 'incorrect_password' => __('The password you entered is incorrect.', 'keyless-auth'), 453 'invalidcombo' => __('Invalid username or password.', 'keyless-auth'), 454 'empty_username' => __('Please enter your username or email address.', 'keyless-auth'), 455 'empty_password' => __('Please enter your password.', 'keyless-auth'), 456 'invalid_email' => __('Invalid email address.', 'keyless-auth'), 457 'invalidkey' => __('Your password reset link is invalid or has expired.', 'keyless-auth'), 458 'expiredkey' => __('Your password reset link has expired. Please request a new one.', 'keyless-auth'), 459 460 // Login status messages (from ?login= parameter) 461 'failed' => __('Login failed. Please try again.', 'keyless-auth'), 462 ); 463 464 // Check error code first 465 if (!empty($error_code) && isset($error_messages[$error_code])) { 466 return $error_messages[$error_code]; 467 } 468 469 // Check login status 470 if (!empty($login_status) && isset($error_messages[$login_status])) { 471 return $error_messages[$login_status]; 472 } 473 474 // Generic fallback for unknown errors 475 if (!empty($error_code) || !empty($login_status)) { 476 return __('Login failed. Please try again.', 'keyless-auth'); 477 } 478 479 return ''; 480 } 481 482 /** 393 483 * Handle form submission 394 484 */ … … 585 675 } 586 676 677 // Preserve error parameters when redirecting 678 $redirect_url = $custom_login_url; 679 $params_to_preserve = array(); 680 681 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters for error display, no security impact 682 if (isset($_GET['login'])) { 683 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters from WordPress redirect 684 $params_to_preserve['login'] = sanitize_text_field(wp_unslash($_GET['login'])); 685 } 686 687 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters for error display, no security impact 688 if (isset($_GET['error'])) { 689 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters from WordPress redirect 690 $params_to_preserve['login_error'] = sanitize_text_field(wp_unslash($_GET['error'])); 691 } 692 693 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters for success messages, no security impact 694 if (isset($_GET['loggedout'])) { 695 $params_to_preserve['loggedout'] = 'true'; 696 } 697 698 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters for success messages, no security impact 699 if (isset($_GET['registered'])) { 700 $params_to_preserve['registered'] = 'true'; 701 } 702 703 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters for success messages, no security impact 704 if (isset($_GET['checkemail'])) { 705 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters from WordPress redirect 706 $params_to_preserve['checkemail'] = sanitize_text_field(wp_unslash($_GET['checkemail'])); 707 } 708 709 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters for redirect URL, no security impact 710 if (isset($_GET['redirect_to'])) { 711 // phpcs:ignore WordPress.Security.NonceVerification.Recommended -- GET parameters from WordPress redirect 712 $params_to_preserve['redirect_to'] = esc_url_raw(wp_unslash($_GET['redirect_to'])); 713 } 714 715 // Add preserved parameters to redirect URL 716 if (!empty($params_to_preserve)) { 717 $redirect_url = add_query_arg($params_to_preserve, $custom_login_url); 718 } 719 587 720 // Perform the redirect 588 wp_redirect($custom_login_url); 721 wp_redirect($redirect_url); 722 exit; 723 } 724 725 /** 726 * Handle failed login attempts 727 * 728 * Redirects to custom login page with error parameters when authentication fails 729 * 730 * @param string $username Username or email used in login attempt 731 * @param WP_Error $error WP_Error object containing error details 732 */ 733 public function handle_failed_login($username, $error) { 734 // Check if custom login redirect is enabled 735 $redirect_enabled = get_option('chrmrtns_kla_redirect_wp_login', '0'); 736 if ($redirect_enabled !== '1') { 737 return; 738 } 739 740 // Check if custom login URL is configured 741 $custom_login_url = get_option('chrmrtns_kla_custom_login_url', ''); 742 if (empty($custom_login_url)) { 743 return; 744 } 745 746 // Get the error code from WP_Error object 747 $error_code = $error->get_error_code(); 748 749 // Build redirect URL with error parameter 750 $redirect_url = add_query_arg('login_error', $error_code, $custom_login_url); 751 752 // Also preserve the username for better UX (optional) 753 if (!empty($username)) { 754 $redirect_url = add_query_arg('login', sanitize_text_field($username), $redirect_url); 755 } 756 757 // Perform the redirect 758 wp_redirect($redirect_url); 589 759 exit; 590 760 } -
keyless-auth/trunk/keyless-auth.php
r3389048 r3390737 4 4 * Plugin URI: https://github.com/chrmrtns/keyless-auth 5 5 * Description: Enhanced passwordless authentication with magic email links, two-factor authentication, SMTP integration, WooCommerce integration, and comprehensive security features for WordPress. 6 * Version: 3.2. 16 * Version: 3.2.2 7 7 * Author: Chris Martens 8 8 * Author URI: https://github.com/chrmrtns -
keyless-auth/trunk/readme.txt
r3389048 r3390737 6 6 Requires at least: 3.9 7 7 Tested up to: 6.8 8 Stable tag: 3.2. 18 Stable tag: 3.2.2 9 9 License: GPLv2 or later 10 10 License URI: https://www.gnu.org/licenses/gpl-2.0.html … … 315 315 316 316 == Changelog == 317 318 = 3.2.2 = 319 * FIX: Login error display on custom login pages - Wrong password/username errors now display properly instead of blank error 320 * FIX: wp_login_failed hook integration - Failed login attempts now redirect to custom login page with error parameters 321 * IMPROVEMENT: Error messages preserved during wp-login.php to custom page redirect flow 322 * IMPROVEMENT: Better error handling for standard WordPress password forms on custom login pages 323 * TECHNICAL: Added handle_failed_login() method to catch authentication failures and redirect with error codes 324 * TECHNICAL: Error parameters (login_error, login) now properly preserved and displayed via shortcodes 325 * COMPATIBILITY: Works harmoniously with User Enumeration Prevention feature - no conflicts 317 326 318 327 = 3.2.1 =
Note: See TracChangeset
for help on using the changeset viewer.