0

I am creating new users using Rest API provided by Services module.

The user creation goes well, but when I try to login with the user I've just created it says wrong password.

The website where I'm testing is not really Drupal, it's Open Atrium, that is based on Drupal but I don't know if that has something to do with my problem but just wanted to mention it.

In the CHANGES file it says Drupal 7.28, 2014-05-08

If I then go to Admin panel and manually change the password for that user, then I can login, but that's the problem, if I create the user from the api I cannot login it says wrong password.

So I think it must be something wrong with how the password gets encrypted inside Drupal when using the api call. I am passing it as plain text.

Any help is appreciated I've spent already lots of time on this.

The code I use to create the user is this:

/*
    * Server REST - user.login
    */
    // REST Server URL
    $request_url = $host.'/rest/user/login';

    // User data
    $user_data = array(
      'username' => /*admin login*/$adminLogin,
      'password' => /*admin password*/$adminPassword,
    );
    $user_data = json_encode($user_data);

    // cURL
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $request_url);
    curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept: application/json', "Content-type: application/json"));
    curl_setopt($curl, CURLOPT_POST, 1); // Do a regular HTTP POST
    curl_setopt($curl, CURLOPT_POSTFIELDS, $user_data); // Set POST data
    curl_setopt($curl, CURLOPT_HEADER, FALSE);  // Ask to not return Header
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($curl, CURLOPT_FAILONERROR, TRUE);
    $response = curl_exec($curl);
    $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    // Check if login was successful
    if ($http_code == 200) {
      // Convert json response as array
      $logged_user = json_decode($response);
    }
    else {
      // Get error msg
      $http_message = curl_error($curl);
      //die($http_message);
      $oa_errors[]="Could not login to OpenAtrium. ($http_message)";
      return false;
    }
    // Define cookie session
    $cookie_session = $logged_user->session_name . '=' . $logged_user->sessid;
    //GET CSRF TOKEN
    $csrf_token = $logged_user->token;
    /*
    * Server REST - user.create
    */
    // REST Server URL
    $request_url = $host.'/rest/user/register';
    // User data
    $user_data = array(
      'name' => /*user name*/ $userName,
      'pass' => /*password*/ $userPassword,
      //'pass1' => /*password*/ $userPassword,
      'mail' => /*email*/ $userEmail,
      'status' => 1,
      //'roles'=>array(
      //  2,
      //  4,
      //),
      'field_user_display_name' => array(
        'und' => array (
            0 => array (
                'value' => /*screen name*/ $userScreenName,
                'format' => NULL,
                'safe_value' => /*screen name*/ $userScreenName,
            ),
        ),
      ),
    );



    $request_url = $host.'/rest/user';
    $user_data = array('account'=>array(
      'name'=>'test_user',  
      'pass'=>'test_pass',
      'mail'=>'[email protected]',
      'field_user_display_name' => array(
        'und' => array (
            0 => array (
                'value' => /*screen name*/ $userScreenName,
                'format' => NULL,
                'safe_value' => /*screen name*/ $userScreenName,
            ),
        ),
      ),
    ));


    print_r($user_data);

    $user_data = json_encode($user_data);

    // cURL
    $curl = curl_init();
    curl_setopt($curl, CURLOPT_URL, $request_url);
    curl_setopt($curl, CURLOPT_POST, TRUE); // Do a regular HTTP POST
    curl_setopt($curl, CURLOPT_HTTPHEADER, array('Accept: application/json', "Content-type: application/json", 'X-CSRF-Token: '.$csrf_token));
    curl_setopt($curl, CURLOPT_POSTFIELDS, $user_data); // Set POST data
    curl_setopt($curl, CURLOPT_HEADER, false);  // Ask to not return Header
    curl_setopt($curl, CURLOPT_COOKIE, "$cookie_session"); // use the previously saved session
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, TRUE);
    curl_setopt($curl, CURLOPT_FAILONERROR, FALSE); //True in prod, false for debugging
    $response = curl_exec($curl);
    $http_code = curl_getinfo($curl, CURLINFO_HTTP_CODE);

1 Answer 1

2

I think I've managed to solve this on my own but with a really strange solution.

I have looked inside the Services module from Drupal to see if I can find what function is getting called when I make the api call to create a new user and I've found this:

/openatrium/modules/services/resources/user_resource.inc

In this file there is this function that is getting called:

/**
 * Create a new user.
 *
 * This function uses drupal_form_submit() and as such expects all input to match
 * the submitting form in question.
 *
 * @param $account
 *   A object containing account information. The $account object should
 *   contain, at minimum, the following properties:
 *     - name (user name)
 *     - mail (email address)
 *     - pass (plain text unencrypted password)
 *
 *   These properties can be passed but are optional
 *     - status (0 for blocked, otherwise will be active by default)
 *     - notify (1 to notify user of new account, will not notify by default)
 *
 *  Roles can be passed in a roles property which is an associative
 *  array formatted with '<role id>' => '<role id>', not including
 *  the authenticated user role, which is given by default.
 *
 * @return
 *   The user object of the newly created user.
 */
function _user_resource_create($account) {

  // Adds backwards compatability with regression fixed in #1083242
  $account = _services_arg_value($account, 'account');

  // Load the required includes for saving profile information
  // with drupal_form_submit().
  module_load_include('inc', 'user', 'user.pages');

  // register a new user
  $form_state['values'] = $account;
  // Password may be not available as this callback is used for register as well.
  $form_state['values']['pass'] = array(
    'pass1' => isset($account['pass']) ?: '',
    'pass2' => isset($account['pass']) ?: '',
  );
  $form_state['values']['op'] = variable_get('services_user_create_button_resource_create', t('Create new account'));

  // execute the register form
  $form_state['programmed_bypass_access_check'] = FALSE;
  drupal_form_submit('user_register_form', $form_state);
  // find and store the new user into the form_state
  if(isset($form_state['values']['uid'])) {
    $form_state['user'] = user_load($form_state['values']['uid']);
  }

  // Error if needed.
  if ($errors = form_get_errors()) {
    return services_error(implode(" ", $errors), 406, array('form_errors' => $errors));
  }
  else {
    $user = array('uid' => $form_state['user']->uid);
    if ($uri = services_resource_uri(array('user', $user['uid']))) {
      $user['uri'] = $uri;
    }
    return $user;
  }
}

You can see this block here is doing something with the password, and what it actually does is setting both pass1 and pass2 fields to value "1", yeah, strange:

  // Password may be not available as this callback is used for register as well.
  $form_state['values']['pass'] = array(
    'pass1' => isset($account['pass']) ?: '',
    'pass2' => isset($account['pass']) ?: '',
  );

I have modified those lines to this:

// Password may be not available as this callback is used for register as well.
  $form_state['values']['pass'] = array(
    'pass1' => isset($account['pass']) ?$account['pass']: '',
    'pass2' => isset($account['pass']) ?$account['pass']: '',
  );

And what this will do is, if you pass a password when making the call it will populate both pass1 and pass2 with it, and if not, it will leave it to blank ''.

This way the user got created and I've managed to login correctly.

As I said this behaviour is strange and I don't understand howcome nobody else had this problem.

I'm also thinking maybe another solution would work, to make a 3rd api call after creating the user, to modify it and set the password again and see if that way it gets updated correctly.

1
  • I came across the same problem. Please do make a post if you find an alternate solution for this. Thanks for your help. It worked for me.
    – Aparna
    Sep 15, 2014 at 5:09

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.