Title: Custom XML-RPC authentication
Last modified: August 20, 2016

---

# Custom XML-RPC authentication

 *  [charlielove](https://wordpress.org/support/users/charlielove/)
 * (@charlielove)
 * [14 years, 4 months ago](https://wordpress.org/support/topic/custom-xml-rpc-authentication/)
 * I use a modified simpleSAMLphp SSO authentication plugin for my blog network 
   to allows a single sign-on using my main user database and then users are automatically
   authenticated/created in WordPress. The simpleSAMLphp plugin breaks XML-RPC authenticate,
   I know why and I’m happy enough with this BUT to provide a fix for users who 
   want to use the WordPress mobile apps and other XML-RPC tools I have written 
   a plug-in which allows users to set up a separate password for XML-RPC use which
   is stored in the user meta data table.
 * The problem is I can’t figure our how to extend the `login_pass_ok` or `login`
   functions in class-wp-xmlrpc-server.php to allow my intended additional user 
   password to be used. My plugin code looks like this at them moment.
 *     ```
       <?php
       /*
       Plugin Name: XML RPC Separate Password
       Plugin URI: http://dropdesign.co.uk/wordpress/xml_rpc_separate_password/
       Description: Creates XML-RPC Password pages under Users menu to allow a separate password to be set for XML-RPC use.  This is useful for WordPress setups where the main autheticate is external such as using SAML, LDAP or similar.
       Version: 1.0
       Author: Charlie Love
       Author URI: http://charlielove.org
       Text Domain: xml-rpc-separate-password
   
       This program is free software; you can redistribute it and/or modify
       it under the terms of the GNU General Public License as published by
       the Free Software Foundation; either version 2 of the License, or
       (at your option) any later version.
   
       This program is distributed in the hope that it will be useful,
       but WITHOUT ANY WARRANTY; without even the implied warranty of
       MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
       GNU General Public License for more details.
   
       You should have received a copy of the GNU General Public License
       along with this program; if not, write to the Free Software
       Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
       */
   
       include_once(ABSPATH . WPINC . '/class-IXR.php');
       include_once(ABSPATH . WPINC . '/class-wp-xmlrpc-server.php');
   
       // for future use with localisation
       //load_plugin_textdomain('xml-rpc-separate-password', false, basename(dirname(__FILE__)) . 'languages/');
   
       //add the actions for the dashboard menus
       add_action('admin_menu', 'xml_rpc_separate_password_init');
       add_action('admin_init', 'xml_rpc_separate_password_check');
   
       //Add a filter for XML RPC class - we'll replace the login check in the class with our one
       add_filter( 'wp_xmlrpc_server_class', 'replace_xmlrpc_server_class' );
   
       function xml_rpc_separate_password_init () {
           add_submenu_page('users.php', __('Set Password for Mobile/XML-RPC App', 'xml-rpc-separate-password'), __('XML-RPC Password', 'xml-rpc-separate-password'), 0, 'change-password', 'xml_rpc_separate_password_pw');
       }
   
       function xml_rpc_separate_password_check () {
           if (isset($_GET['page']) && ($_GET['page'] == 'change-password' )) {
               wp_enqueue_script('user-profile');
               wp_enqueue_script('password-strength-meter');
               if (!empty($_POST)) {
                   global $wpdb, $user_ID, $user_email;
                   get_currentuserinfo();
                   $user = get_userdata($user_ID);
       			//write this password into the user meta data - DO NOT TOUCH THE CORE WORDPRESS USER PASSWORD
                   if (isset($_POST['pass1']) && isset($_POST['pass2']) && !empty($_POST['pass1']) && $_POST['pass1'] == $_POST['pass2']) {
       				//write the new xml-rpc authentication password into the user meta using the standard wp encryption for passwords
       			    $update = update_user_meta( $user_ID, 'xml_rpc_password', array(wp_hash_password($_POST['pass1'])));
       				//if it hasn't screwed up say it's all super-duper!
                       if (!is_wp_error($update)) {
                           ob_start();
       ?>
                       <div id="message" class="updated fade">
                           <p><strong><?php _e('Password updated.') ?></strong></p>
                       </div>
       <?php
                                           $_POST['post_msg'] = ob_get_clean();
                       }
       				//eck, screwed up - fail!
                       if (is_wp_error($update)) {
                           ob_start();
       ?>
                       <div class="error">
                           <ul>
       <?php
                           foreach ($update->get_error_messages() as $message) {
       ?>
                               <li><?php echo $message; ?></li>
       <?php
                           }
       ?>
                           </ul>
                       </div>
       <?php
                           $_POST['post_msg'] = ob_get_clean();
                       }
                   }
               }
           }
       }
   
       function xml_rpc_separate_password_pw () {
           global $wpdb, $user_ID;
           $title = __('Update Password for Mobile/XML-RPC Services');
           $what = 'change-password';
           $user = get_userdata($user_ID);
           if (isset($_POST['post_msg']))
               echo $_POST['post_msg'];
       ?>
       <div class="wrap" id="profile-page">
           <?php screen_icon(); ?>
           <h2><?php echo esc_html($title); ?></h2>
           <form id="your-profile" action="" method="post">
               <table class="form-table">
                   <tr id="password">
                       <th><label for="pass1"><?php _e('New Password'); ?></label></th>
                       <td><input type="password" name="pass1" id="pass1" size="16" value="" autocomplete="off" />
                           <span class="description"><?php _e("If you would like to change the password type a new one. Otherwise leave this blank."); ?></span><br />
                           <input type="password" name="pass2" id="pass2" size="16" value="" autocomplete="off" />
                           <span class="description"><?php _e("Type your new password again."); ?></span><br />
   
                           <div id="pass-strength-result"><?php _e('Strength indicator'); ?></div>
                           <p class="description indicator-hint"><?php _e('Hint: The password should be at least seven characters long. To make it stronger, use upper and lower case letters, numbers and symbols like ! " ? $ % ^ & ).'); ?></p>
                       </td>
                   </tr>
               </table>
               <p class="submit">
                   <input type="hidden" name="user_login" id="user_login" value="<?php echo $user->user_login; ?>" />
                   <input type="submit" class="button-primary" value="<?php esc_attr_e('Update Password') ?>" name="submit" />
               </p>
           </form>
       </div>
       <?php
       }
   
       //now the serious stuff to authenticate XML-RPC calls using our saved user-meta password rather than the default WP user one!
   
       /**
        * Generate the Response
        *
        * @param methods Array - list of existing XMLRPC methods
        * @return methods Array - list of updated XMLRPC methods
        */
       function replace_xmlrpc_server_class( $class_name ) {
       	// only replace the default XML-RPC class if another plug-in hasn't already changed it
       	if ( $class_name === 'wp_xmlrpc_server' )
       		return 'wp_xmlrpc_server_ext';
       	else
       		return $class_name;
       }
   
       class wp_xmlrpc_server_ext extends wp_xmlrpc_server {
   
       	function __construct() {
       		// hook filter to add the new methods after the existing ones are added in the parent constructor
       		add_filter( 'xmlrpc_methods' , array( &$this, 'xmlrpc_methods' ) );
   
       		parent::__construct();
       	}
   
       	function xmlrpc_methods ( $methods ) {
       		$new_methods = array();
       		// array_merge will take the values defined in later arguments, so
       		// the plugin will not overwrite any methods defined by WP core
       		// (i.e., plugin will be forward-compatible with future releases of WordPress
       		//  that include these methods built-in)
       		return array_merge( $new_methods, $methods );
       	}
   
       	//replace the login functions
       	/**
       	 * Check user's credentials.
       	 *
       	 * @param string $user_login User's username.
       	 * @param string $user_pass User's password.
       	 * @return bool Whether authentication passed.
       	 * @deprecated use wp_xmlrpc_server::login
       	 * @see wp_xmlrpc_server::login
       	 */
       	function login_pass_ok($user_login, $user_pass) {
       		if ( !get_option( 'enable_xmlrpc' ) ) {
       			$this->error = new IXR_Error( 405, sprintf( __( 'XML-RPC services are disabled on this site.  An admin user can enable them at %s'),  admin_url('options-writing.php') ) );
       			return false;
       		}
   
       	    // Let's run a check to see if credentials are okay
       	    if (!function_exists('get_userdatabylogin'))
       	         return new IXR_Error( 403, __( 'No user validation available.' ) );
   
       		//retrieve the user using the username
       		$user = get_userdatabylogin($user_login);
       		if(!$user)
       	         return new IXR_Error( 403, __( 'User does not exist.' ) );
   
       		//get the user id from the user data
       		$user_id = $user->ID;
   
       		//retreive the stored hashed password array from the usermeta
       		$password_array = get_user_meta($user_id,'xml_rpc_password');
   
       		//stored the hashed password in an array so extract the hashed password from the array
       		$hashed_stored_password = $password_array[0];
   
       		//validate the hashed password with the user supplied one from XML-RPC
       		if ( !wp_check_password($user_pass,$hashed_stored_password) ) {
       			$this->error = new IXR_Error(403, __('Bad login/pass combination.'));
       			return false;
       		}
       		return true;
       	}
   
       	/**
       	 * Log user in.
       	 *
       	 * @since 2.8
       	 *
       	 * @param string $username User's username.
       	 * @param string $password User's password.
       	 * @return mixed WP_User object if authentication passed, false otherwise
       	 */
       	function login($username, $password) {
       		if ( !get_option( 'enable_xmlrpc' ) ) {
       			$this->error = new IXR_Error( 405, sprintf( __( 'XML-RPC services are disabled on this site.  An admin user can enable them at %s'),  admin_url('options-writing.php') ) );
       			return false;
       		}
   
       	    // Let's run a check to see if credentials are okay
       	    if (!function_exists('get_userdatabylogin'))
       	         return new IXR_Error( 403, __( 'No user validation available.' ) );
   
       		//retrieve the user using the username
       		$user = get_userdatabylogin($user_login);
       		if(!$user)
       	         return new IXR_Error( 403, __( 'User does not exist.' ) );
   
       		//get the user id from the user data
       		$user_id = $user->ID;
   
       		//retreive the stored hashed password array from the usermeta
       		$password_array = get_user_meta($user_id,'xml_rpc_password');
   
       		//stored the hashed password in an array so extract the hashed password from the array
       		$hashed_stored_password = $password_array[0];
   
       		//validate the hashed password with the user supplied one from XML-RPC
       		if ( !wp_check_password($user_pass,$hashed_stored_password) ) {
       			$this->error = new IXR_Error(403, __('Bad login/pass combination.'));
       			return false;
       		}
   
       		wp_set_current_user( $user->ID );
       		return $user;
       	}	
   
       }
   
       ?>
       ```
   
 * I could just hack the class-wp-xmlrpc-server.php file and replace the two functions
   but I would much rather have something that works correctly as a plug. Any ideas
   how I can replace the functionality of these two functions?

Viewing 2 replies - 1 through 2 (of 2 total)

 *  [Hadis](https://wordpress.org/support/users/hadis89/)
 * (@hadis89)
 * [14 years, 2 months ago](https://wordpress.org/support/topic/custom-xml-rpc-authentication/#post-2475846)
 * can you write how to hack class-wp-xmlrpc-server.php?
 *  [slbmeh](https://wordpress.org/support/users/slbmeh/)
 * (@slbmeh)
 * [14 years ago](https://wordpress.org/support/topic/custom-xml-rpc-authentication/#post-2475859)
 * This is a rather old post, but I’ll add my two cents in case anyone were to find
   this post trying to provide similar functionality.
 * Most authentication in my experience provide authentication support by use of
   the ‘wp_authenticate’ hook that is used called in wp-login.php. The xmlrpc server
   login does not call the authenticate hook, but instead calls the wp_authenticate
   function. Additionally, the login_pass_ok calls user_pass_ok, which then also
   calls wp_authenticate.
 * The wp_authenticate function is defined in pluggable.php, so you can write a 
   plugin that overrides the wp_authenticate function and calls the wp_authenticate
   action and should provide authentication through xmlrpc and any other scripted
   method that calls wp_authenticate.

Viewing 2 replies - 1 through 2 (of 2 total)

The topic ‘Custom XML-RPC authentication’ is closed to new replies.

## Tags

 * [authentication](https://wordpress.org/support/topic-tag/authentication/)
 * [SSO](https://wordpress.org/support/topic-tag/sso/)
 * [XML-RPC](https://wordpress.org/support/topic-tag/xml-rpc/)

 * In: [Hacks](https://wordpress.org/support/forum/plugins-and-hacks/hacks/)
 * 2 replies
 * 3 participants
 * Last reply from: [slbmeh](https://wordpress.org/support/users/slbmeh/)
 * Last activity: [14 years ago](https://wordpress.org/support/topic/custom-xml-rpc-authentication/#post-2475859)
 * Status: not resolved

## Topics

### Topics with no replies

### Non-support topics

### Resolved topics

### Unresolved topics

### All topics
