How to Use the Password Hashes Export from Auth0

Last Updated: Sep 27, 2024

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’s good to clarify a couple of them related to the user id. A sample single user would look like this (formatted for better readability):

{
  "_id":{"$oid":"5dea9f9c82dd7c0e76e4ec93"},
  "email_verified":false,
  "email":"nico9090@nico.com",
  "passwordHash":"$2b$10$.qHPp/srqo1NAAAAAvlkmOdqAbH2Rg0qPv2Txj3ZwXfjJnewSjc4m",
  "password_set_date":{"$date":"2019-12-06T18:36:12.412Z"},
  "tenant":"nico-sabena",
  "connection":"Username-Password-Authentication",
  "_tmp_is_unique":true,
  "alt_id":"euclid"
}

Every user will have an _id field, while the alt_id is optional. alt_id will be present on users coming from a custom DB (where the custom DB script provides the user id) or when creating regular DB connection users with the Management API v2 and providing 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 that is the field that indicates where the user came from.

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":"nico9090@nico.com",
    "password_hash":"$2b$10$.qHPp/srqo1NAAAAAvlkmOdqAbH2Rg0qPv2Txj3ZwXfjJnewSjc4m"
  },
  {...} // 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":"nico9090@nico.com",
    "password_hash":"$2b$10$.qHPp/srqo1NAAAAAvlkmOdqAbH2Rg0qPv2Txj3ZwXfjJnewSjc4m"
  },
  {...} // 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/migrate metadata or other information too?

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 Management API v2) and merge that data with the password hashes provided by Auth0 support so that the final import file has all the data. E.g.:

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

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