Hello Keycloak community,
I’m facing a challenge migrating a user with a WebAuthn (YubiKey) credential between two identical Keycloak instances (test1.company.dev and test2.company.dev). Both instances are configured with the same RPID/sub-domain for WebAuthn policies.
Problem:
-
I registered a YubiKey for a user on
test1.company.dev, and it works correctly. -
I exported this user’s data into a users.json file (including their password and
webauthn-passwordlesscredentials). -
I performed a partial realm import of this user into
test2.company.devvia the Admin API. The user and both their credentials appear in thetest2admin console. -
However, when I try to log in to
test2with the YubiKey, I get errors saying that the YubiKey isn’t connected or is connected to a different user.
My Understanding & Suspicions:
It seems the credentialId of the WebAuthn token might be strongly tied to Keycloak’s internal user.id. Even though I’m importing the user with the same id from the source instance, the target instance might be having a conflict or mismatch in this internal mapping.
Specific Questions:
-
Is the user’s
idfrom the import JSON directly linked to the WebAuthncredentialIdin a way that causes this conflict during migration? -
What is the recommended, robust method for programmatically migrating users with existing WebAuthn credentials between identical Keycloak instances?
-
Are there specific fields within the WebAuthn credential data (e.g., the
idfield for the credential,counter) that need special handling or omission during such an import? -
Could this error suggest a
credentialIdcollision intest2.dev’s database, possibly from a prior failed attempt?
Any insights or best practices for ensuring smooth WebAuthn credential migration would be highly appreciated. My goal is to avoid requiring users to re-register their YubiKeys when moving between Keycloak environments.
Note that I am operating in a highly partitioned environment and so need to have multiple instances of KC running separately and then manually sync. This is the part of the manual sync that I am having problems smoketesting.
Thank you!
User Credentials Format that I am using:
{
“id”: “SOME_HASH”,
“type”: “webauthn-passwordless”,
“createdDate”: 1764194058611,
“secretData”: “{}”,
“credentialData”: “{\“aaguid\”:\“00000000-0000-0000-0000-000000000000\”,\“credentialId\”:\“COPIED_FROM_TEST1.COMPANY.DEV\”,\“counter\”:5,\“credentialPublicKey\”:\“COPIED_FROM_TEST1.COMPANY.DEV\”,\“attestationStatementFormat\”:\“none\”,\“transports\”:[\“usb\”]}”
}
\]