OOKIE['llar_mfa_state'] ) ? sanitize_text_field( wp_unslash( $_COOKIE['llar_mfa_state'] ) ) : ''; if ( ! $session || empty( $session['secret'] ) || empty( $session['username'] ) ) { return; } $verify = $store->consume_callback_state( $cookie, $token ); SessionStore::set_state_cookie( '' ); if ( ! $verify ) { $store->delete_session( $token ); self::redirect_login( 'llar_mfa_session_expired' ); exit; } if ( empty( $session['is_pre_authenticated'] ) ) { return; } $provider_id = isset( $session['provider_id'] ) ? $session['provider_id'] : 'llar'; $provider = MfaProviderRegistry::get( $provider_id ); if ( ! $provider ) { return; } $result = $provider->verify( $token, $session['secret'] ); if ( ! $result['success'] || empty( $result['data']['is_verified'] ) ) { return; } $user_id = ! empty( $session['user_id'] ) ? (int) $session['user_id'] : 0; $user = $user_id ? get_user_by( 'id', $user_id ) : get_user_by( 'login', $session['username'] ); if ( ! $user || ! is_a( $user, 'WP_User' ) ) { return; } wp_clear_auth_cookie(); wp_set_current_user( $user->ID ); $remember_me = ! empty( $session['remember_me'] ); wp_set_auth_cookie( $user->ID, $remember_me ); self::record_successful_login( $user, $session['username'] ); $redirect_to = ! empty( $session['redirect_to'] ) ? $session['redirect_to'] : ''; $redirect_url = ( $redirect_to && self::is_safe_redirect( $redirect_to ) ) ? $redirect_to : admin_url(); wp_safe_redirect( $redirect_url ); $store->delete_session( $token ); exit; } /** * Handle callback: load session, verify OTP and API, then login and redirect. * * @param string $token Session token. * @param string $code User-entered OTP code. */ public static function handle( $token, $code ) { $store = new SessionStore(); $session = $store->get_session( $token ); $cookie = isset( $_COOKIE['llar_mfa_state'] ) ? sanitize_text_field( wp_unslash( $_COOKIE['llar_mfa_state'] ) ) : ''; if ( ! $session || empty( $session['secret'] ) || empty( $session['username'] ) ) { $store->delete_session( $token ); self::redirect_login( 'llar_mfa_session_expired' ); return; } $verify = $store->consume_callback_state( $cookie, $token ); SessionStore::set_state_cookie( '' ); if ( ! $verify ) { $store->delete_session( $token ); self::redirect_login( 'llar_mfa_session_expired' ); return; } if ( ! $store->verify_otp_once( $token, $code ) ) { $store->delete_session( $token ); self::redirect_login( 'llar_mfa_code_invalid' ); return; } $provider_id = isset( $session['provider_id'] ) ? $session['provider_id'] : 'llar'; $provider = MfaProviderRegistry::get( $provider_id ); if ( ! $provider ) { $store->delete_session( $token ); self::redirect_login( 'llar_mfa_verify_failed' ); return; } $result = $provider->verify( $token, $session['secret'] ); if ( ! $result['success'] || empty( $result['data']['is_verified'] ) ) { $store->delete_session( $token ); self::redirect_login( 'llar_mfa_verify_failed' ); return; } $user_id = ! empty( $session['user_id'] ) ? (int) $session['user_id'] : 0; $user = $user_id ? get_user_by( 'id', $user_id ) : get_user_by( 'login', $session['username'] ); if ( ! $user || ! is_a( $user, 'WP_User' ) ) { $store->delete_session( $token ); self::redirect_login( 'llar_mfa_user_invalid' ); return; } if ( empty( $session['is_pre_authenticated'] ) ) { $store->delete_session( $token ); self::redirect_login( 'llar_mfa_pre_auth_required' ); return; } wp_clear_auth_cookie(); wp_set_current_user( $user->ID ); $remember_me = ! empty( $session['remember_me'] ); wp_set_auth_cookie( $user->ID, $remember_me ); self::record_successful_login( $user, $session['username'] ); $redirect_to = ! empty( $session['redirect_to'] ) ? $session['redirect_to'] : ''; $redirect_url = ( $redirect_to && self::is_safe_redirect( $redirect_to ) ) ? $redirect_to : admin_url(); wp_safe_redirect( $redirect_url ); $store->delete_session( $token ); exit; } /** * Redirect to login with optional message key. * * @param string $msg_key Optional. Query arg for message. */ private static function redirect_login( $msg_key = '' ) { $url = wp_login_url(); if ( $msg_key ) { $url = add_query_arg( 'llar_mfa_error', $msg_key, $url ); } wp_safe_redirect( $url ); } /** * Check if redirect URL is safe (same host or allowed). * * @param string $url Redirect URL. * @return bool */ private static function is_safe_redirect( $url ) { $allowed = wp_validate_redirect( $url, false ); return ( $allowed !== false ); } }