Aller au contenu

Export users from Ory Kratos

Ce contenu n’est pas encore disponible dans votre langue.

This guide walks through exporting the identities of a self-hosted Ory Kratos instance into the Canonical Migration Format (CMF), checking what came out, and preparing the result for import into another provider.

iamigrate export --source kratos reads every identity through the Admin API (GET /admin/identities), 250 per page, following Kratos’ pagination links until the last page. It requests each identity’s password credential, so password hashes are exported and users can keep their password on the target.

Each identity becomes one CMF user. Identities that can’t be translated are skipped and listed in manifest.json instead of failing the export.

  • iamigrate installed (see Installation).
  • Network access to the instance’s Admin API, usually on port 4434.

The export contains password hashes and personal data. Write it somewhere access-controlled, and delete it once the migration is done.

Terminal window
export KRATOS_ADMIN_URL=http://127.0.0.1:4434
iamigrate export --source kratos --out ./export/
exported 1250 users -> export/users.cmf.jsonl.gz (3 skipped)

You can pass --admin-url instead of setting $KRATOS_ADMIN_URL. The command writes:

export/
├── users.cmf.jsonl.gz # one CMF user per exported identity
├── manifest.json # counts per hash algorithm, plus skipped identities
└── mapping.yaml # scaffolded mapping, with no target set yet

The export is a snapshot. Identities created, and passwords changed, after it runs aren’t in it, so plan a freeze or a final re-export before cutover.

Terminal window
cat export/manifest.json
{
"record_count": 1250,
"hash_algorithm_counts": {
"argon2": 120,
"bcrypt": 1130
},
"skipped_records": [
{
"source_id": "140625ed-95b8-41b3-8882-c3adee5833f8",
"reason": "missing hashed_password on identity's password credential"
}
]
}
  • hash_algorithm_counts tells you which algorithms the target must accept. Kratos stores bcrypt or argon2 (argon2id) hashes, depending on its hashers config.
  • skipped_records lists identities that aren’t in users.cmf.jsonl.gz, by Kratos identity ID.
Skip reasonCause
missing hashed_password on identity's password credentialThe identity has no password hash, for example because it was created through the Admin API without one
unrecognized password hash format: ...The stored hash isn’t a format iamigrate recognizes

Skipped identities aren’t migrated at all. If you need them on the target, recreate them there and have them set a password, or sign in with the same method they used on Kratos.

Kratos fieldCMF field
idsource_id
traits.emailemails[0], marked primary. Verified if a matching verifiable_addresses entry is verified.
traits.usernameusername
state: inactiveblocked: true
metadata_adminapp_metadata
metadata_publicuser_metadata
credentials.password.config.hashed_passwordpassword, with the algorithm and parameters detected from the hash

The Kratos identity UUID becomes source_id, and is what import reports refer to. Some targets reuse it as the user ID; for example, Auth0 turns it into auth0|<uuid>.

  • Other traits. Only email and username are read. Names, phone numbers, and any custom traits are dropped, so profile is empty on every exported user.
  • MFA. TOTP, recovery codes (lookup_secret), and WebAuthn credentials aren’t exported. Users have to set up a second factor again on the target.
  • Social sign-in links (oidc credentials).
  • Recovery addresses and timestamps such as creation date.

If you need any of these, fetch them from the Admin API yourself and merge them into the CMF records, for example adding names to profile with jq, before you import.

mapping.yaml is scaffolded with target: "". Set the target before you validate with it:

Terminal window
iamigrate map --target <target> --mapping ./export/mapping.yaml

Then check the export against the target’s capabilities. No network calls are made:

Terminal window
iamigrate validate --in ./export/users.cmf.jsonl.gz --mapping ./export/mapping.yaml --target <target>

From there, follow the import guide for your target:

To try the export without a real instance, import a fixture into a disposable Kratos (see Import users into Ory Kratos), then export it back:

Terminal window
iamigrate testdata generate --count 50 --hash bcrypt:cost=10 --hash argon2 --out ./fixtures/
iamigrate import kratos --in ./fixtures/users.cmf.jsonl.gz
iamigrate export --source kratos --out ./export/

Every fixture user comes back with the same email and password hash, but with a Kratos UUID as source_id and an empty profile. That’s the data loss described in Step 3.