0

I have a Drupal website and a Symfony based API. I have configured Drupal to use my API for logging in. The users are stored in Symfony.

When logging in, Drupal will store a user in the database to create a user object. On this user object, I want to set some custom properties. For example an id which is a reference back to my Symfony user so that I can load the users settings, etc. later on.

I have not managed to figure out how to do this. I hope someone has an example on how to do this or can point me in the right direction.

Below is the code I use for logging the user in. First I check if the entered username matches an administrator that Drupal knows of. If it does, I will use the default Drupal login validation. If not, I will login through the API.

/**
 *  Validates the login. Uses either the default Drupal validation or a custom validation.
 */
function myy_authenticate_validate($form, &$form_state)
{
    // Retrieve name and password.
    $name = $form_state["values"]["name"];
    $pass = $form_state["values"]["pass"];

    // Check if the user exists in the Drupal users
    if ($user = db_query("SELECT * FROM {users} u WHERE name = :name", array(':name' => $name))->fetch())
    {
        // A user exists. Loads the user information.
        $user = user_load($user->uid);

        // If the user is an administator, log him in using the Drupal validator.
        if (in_array("administrator", $user->roles))
            return user_login_authenticate_validate($form, $form_state);
    }

    // The user didn't exist in the Drupal users. Now, try to authenciate using the custom validation.
    $authenticated = myy_symfony_auth($name, $pass);

    // Check if we did authenciate
    if ($authenticated)
    {
        // This sets up the external user with Drupal by creating a local entry. If they don't exist they are added.
        user_external_login_register($name, "myy");

        // We must set the "uid" to pass back. This looks up the logged in user and sets the Drupal UID.
        $user = user_external_load($name, $pass);
        $form_state["uid"] = $user->uid;
    }
    else
    {
        // Do nothing. Drupal will handle the errors.
    }
}

myy_symfony_auth is a method which returns whether or not we were able to login using the API.

Does anyone have an idea how I can add custom properties to the user object when a login succeeds? It is only relevant to do this when the login was performed using the API (meaning that it was not an administrator who logged in).

1

I've done the same thing in D7. I see you're using the user-login-form directly and skipping over UID = 1 .... thats ok.

What you want todo is essentially copy the PHP logic of user_external_login_register into your own function, you're already calling your own *_authenticate() function to process the login page.

So you would change your:

// This sets up the external user with Drupal by creating a local entry.
// If they don't exist they are added.
user_external_login_register($name, "myy");

To like:

// This sets up the external user with Drupal by creating a local entry.
// If they don't exist they are added.
MYMODULE_user_external_login_register($name, "myy", $external_data);

and define the necessary function that mimics the D7 login logic AND adds you're own fields for the user upon creation (I mean literally copy the D7 function body into your function body and tweak as needed) -- I've added additional fields using the Field UI found at /admin/people to my User accounts as seen below.

So I have this function to do that:

function MYMODULE_auth_idstaff_user_external_login_register($name, $module, $external_ldap_details) {
  $account = user_external_load($name);
  if (!$account) {
    // Register this new user.
    $roles = user_roles();
    $userinfo = array(
      'name' => $name,
      'pass' => user_password(),
      'init' => $name,
      'status' => 1,
      'access' => REQUEST_TIME,
      // This is where we are different from the default function and add our fields.
      'roles'        => array(array_search('staff', $roles) => 1),
      'mail' => $external_ldap_details['mail'],
      'field_first_name'   => array(LANGUAGE_NONE => array( 0 => array('value' => $external_ldap_details['first_name']))),
      'field_last_name'    => array(LANGUAGE_NONE => array( 0 => array('value' => $external_ldap_details['last_name']))),
    );
    $account = user_save(drupal_anonymous_user(), $userinfo);
    // Terminate if an error occurred during user_save().
    if (!$account) {
      drupal_set_message(t("Error saving user account."), 'error');
      return;
    }
    user_set_authmaps($account, array("authname_$module" => $name));
  }

  // Log user in.
  $form_state['uid'] = $account->uid;
  user_login_submit(array(), $form_state);
}

I've actually done the same exact thing in Symfony 1.4.x a few years ago ... except it was all object oriented lol (because Symfony's forms are Objects).

  • Thank you for your answer. I have followed your approach and added the fields using the Field UI. I see that the files are added correctly and I can set the values for the fields when editing a user. The value doesn't seem to be set on login though and I can't figure out how to access the property. The name of my field is ymuid, so I thought I would set the value using $userinfo['field_ymuid'] = "myValue" and access it using $user->field_ymuid. Is there anything besides that I should do as this doesn't seem to work? – SimonBS Aug 9 '12 at 8:30
  • I found that I have to call $user = user_load($user->uid) to load custom fields. Then, accessing a custom field is a bit cumbersome. It should be done like this $ymuid = field_get_items("user", $user, "field_ymuid"); Then get the value using $ymuid[0]["value"]. I still have issues, though. When logging in using my custom implementation of user_external_login_register(), I'll have to login twice to actually be logged in. First time only creates the user. The final issue is that the value for field_ymuid is not set when the user is created. – SimonBS Aug 9 '12 at 9:20
  • Seems like I don't have to login twice when using Firefox but when using Chrome, it's an issue. I'll look into this. – SimonBS Aug 9 '12 at 9:31
  • I read your answer again and I must have overlooked how you specify the value. It should be done using array( 0 => array('value' => $external_details['my_value']))) as you do. Thank you very much for your help! – SimonBS Aug 9 '12 at 9:52
  • did you fix the login twice issue? That could be because the default user_authenticate_validate() is running before your custom authenticate_validate(). I use FAPI on the user login form to replace the default validation function with my own, if you still have this issue I can make another answer to show you how to fix it... – tenken Aug 9 '12 at 13:20

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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