How to Use the Password Hashes Export from Auth0

Overview
This article explains how to migrate users using the Password Hashes export from Auth0.
Applies To
  • Export
  • Password Hashes Export
  • Migrate users
  • Connections
Solution

Data format

The provided file is in NDJSON format (New line delimited JSON). The export file would look like this:

{ ... one user... }
{ ... another user ... }
{ ... and so on ... }


Each user object will have some properties. Most of them are self-explanatory, but it is worth clarifying a couple related to the user ID. A sample single user would look like this (formatted for better readability):

{
  "_id":{"$oid":"5dea9f9c82dd7c0e76e4ec93"},
  "email_verified":false,
  "email":"user@example.com",
  "passwordHash":"$2b$10$.qHPp/srq...REDACTED...",
  "password_set_date":{"$date":"2019-12-06T18:36:12.412Z"},
  "tenant":"example-tenant-name",
  "connection":"Username-Password-Authentication",
  "_tmp_is_unique":true,
  "identifiers":[{"type":"email","value":"user@example.com","verified":false}]
  "alt_id":"euclid"
}


Every user will have an _id field, while the alt_id is optional. alt_id will be present for users coming from a custom DB (where the custom DB script provides the user ID) or for users created with the Management API v2 and provided a custom user ID.

In the above case, the user identifier is likely to be something like auth0|euclid. If the alt_id field was not present, then the full user_id would be auth0|5dea9f9c82dd7c0e76e4ec93. 

The connection parameter is important if the export was requested from multiple databases, as it indicates where the user came from.
 

In some users, the root attributes such as email and email_verified may not be present in the export, but should be consistently available within the identifiers array as "email" and "verified" respectively.

Is it possible to use this file to import directly to Auth0 (e.g., with the Users Import Extension)?

No, not really. The format accepted by the Bulk Import Users API (or extension) is different. The full specification can be found at Bulk User Import Database Schema and Examples. Some important things to consider:

  • The size of the import file is limited to 500kb
  • The expected format is a JSON array, not NDJSON.
  • To import the original user ids, provide a user_id field with the value found in the exported user’s alt_id (if present), or the $oid value.

E.g., for the sample user above:

[
  {
    "user_id":"euclid", // to keep the same user id
    "email_verified":false,
    "email":"user@example.com",
    "password_hash":"$2b$10$.qHPp/srq...REDACTED..."
  },
  {...} // other entries in the array
]


To keep the user id when this user did not have an alt_id:

[
  {
    "user_id":"5dea9f9c82dd7c0e76e4ec93", // to keep the same user id
    "email_verified":false,
    "email":"user@example.com",
    "password_hash":"$2b$10$.qHPp/srq...REDACTED..."
  },
  {...} // other entries in the array
]

 

Using jq to convert data

While it is possible to convert data in different ways, a useful tool is jq.

This command will read an input file (input.json), pipe it through a couple of jq filters, and write it in an output file that’s ready to import (output.json):

cat input.json | jq '{user_id: (if has("alt_id") then .alt_id else ._id."$oid" end), email, username, email_verified, password_hash: .passwordHash}' | jq -s 'del(.[][] | nulls)' > output.json


The first jq pass picks relevant fields, and the second one removes null values and transforms the input into one big array.

The above command will pick the alt_id as the user id, and use the _id.$oid if alt_id is not available.
Alternatively, use the alt_id if present and let Auth0 assign a random user_id if the alt_id is not provided by replacing ._id."$oid with null:

cat input.json | jq '{user_id: (if has("alt_id") then .alt_id else null end), email, username, email_verified, password_hash: .passwordHash}' | jq -s 'del(.[][] | nulls)' > output.json

 

How to add or migrate metadata or other information

The password hashes export provided by Auth0 Support does not include the user metadata fields. To include it, export the data separately (the regular bulk user export from the extension or the Management API v2) and merge it with the password hashes provided by Auth0 support so that the final import file contains all the data. E.g.:

[
  {
    "user_id":"5dea9f9c82dd7c0e76e4ec93", // to keep the same user id
    "email_verified":false,
    "email":"user@example.com",
    "password_hash":"$2b$10$.qHPp/srq...REDACTED...",
    [...], // other properties like these:
    "given_name":"Nicolás",
    "app_metadata": {
      [...]
    },
    "user_metadata": {
      [...]
    }

  },
  {...} // other entries in the array
]

 



Common Reported Issues

For larger exports,  empty "jsonlines" files may be included in the export after decompressing. This is currently expected behaviour and not a sign of missing data, and is instead due to how the query is run.

 

The macOS Archive utility may also show an error: "Unable to expand <EXPORT_FILENAME>.zip into <DESTINATION_FOLDER_NAME>."  If this occurs, it is recommended to try a different archive manager tool to workaround this.

Recommended content

No recommended content found...