Question

I'm trying to migrate users exported from Drupal into Okta using the /api/v1/users API (specifically [creating users with import hash][1]), and am stuck, and desperate for help as I'm late on a project now because I haven't cracked this issue.

FYI

  1. I posted this to both Okta forum: https://devforum.okta.com/t/migrating-users-from-drupal-7-to-okta/13103
  2. and Drupal forum: https://www.drupal.org/forum/support/post-installation/2021-02-27/migrating-users-from-drupal-7-to-okta
  3. I also contacted support@okta.com who weren't able to offer any further advice
  4. And pestered a bunch folk in various places on Slack and Discord.

I think the core issue is that I'm not getting the 'right' value for the hash from the Drupal pass string.

Here's an example of a user:

{ "name" : "m.nick", "first": "Nick", "last" : "M", "mail" : "m.nick@gmail.com", "pass" : "$S$D9./psEr4CRGa61wFXVVxPA4sdxK4IRWPuWJMbbkOHBQNnIoUwOb", }

I believe the $S$ means SHA-512 was used by Drupal, the D means 15 rounds of hashing were performed, character 4-12 are the salt and the rest of the string is the hash?

Here's how I get the settings, salt and hash from the Drupal pass:

const hashType = pass.substring(0,3) const rounds = pass.substring(3,4) const salt = pass.substring(4,12) const hash = pass.substring(12)

I'm then calling /api/v1/users?activate=true with

profile: { firstName: first, lastName: last, email: mail, login: username }, credentials: { password: { hash: { algorithm: 'SHA-512', salt: salt, saltOrder: 'PREFIX', value: hash }}}

Which successfully creates the user, but on attempting sign in with the username: m.nick and the password that works on the old system, gets rejected with INVALID_CREDENTIALS.

I've tried:

  1. Switching the saltOrder to POSTFIX
  2. base64 decoding the hash
  3. base64 decoding and encoding the hash
  4. Concat'ing the salt and the hash together
  5. Every combination of the above

Please help, as I don't know what else to try, and I can't find any examples of Drupal user accounts being imported into Okta.

I'd be grateful for any advice you can offer. I assume that someone has previously migrated users from Drupal, and so I'm missing something.

Was it helpful?

Solution

The number of iterations is wrong. The stored value is the power of 2, encoded using a Base64 alphabet. D means 32768 iterations (215).
The other issue you have is that the hash and salt values are Base64 encoded, but using the same alphabet used by cript() (the POSIX function also part of the BSD Library). The PHP code Drupal uses to encode is the following one. It may be helpful to write the JavaScript code you need.

function _password_base64_encode($input, $count) {
  $output = '';
  $i = 0;
  $itoa64 = _password_itoa64();
  do {
    $value = ord($input[$i++]);
    $output .= $itoa64[$value & 0x3f];
    if ($i < $count) {
      $value |= ord($input[$i]) << 8;
    }
    $output .= $itoa64[$value >> 6 & 0x3f];
    if ($i++ >= $count) {
      break;
    }
    if ($i < $count) {
      $value |= ord($input[$i]) << 16;
    }
    $output .= $itoa64[$value >> 12 & 0x3f];
    if ($i++ >= $count) {
      break;
    }
    $output .= $itoa64[$value >> 18 & 0x3f];
  } while ($i < $count);
  return $output;
}

function _password_itoa64() {
  return './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz';
}

The full code used from Drupal 7 to hash passwords is contained in the password.inc file. In particular check the following functions:

I cannot say what should be used for saltOrder, since that isn't used from Drupal code and it's specific for the platform to which you are migrating the users.

Licensed under: CC-BY-SA with attribution
Not affiliated with drupal.stackexchange
scroll top