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.


  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 [email protected] 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" : "[email protected]", "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.

1 Answer 1


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) {
    if ($i < $count) {
      $value |= ord($input[$i]) << 16;
    $output .= $itoa64[$value >> 12 & 0x3f];
    if ($i++ >= $count) {
    $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.

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.