Skip to main content
When using delegated wallets, your end users control their own signing credentials. If they lose access to their device, they need a way to recover their wallet. This guide covers how to implement recovery flows.
Recovery credentials are encrypted private keys that DFNS stores as an opaque blob. The encryption happens in your frontend. DFNS never sees the decryption password. This means you own the full recovery experience: you decide the encryption scheme, the password format, and the recovery UX. The DFNS dashboard recovery flow at app.dfns.io/recover only works for users who registered their recovery credential through the dashboard.

Recovery strategies

We recommend encouraging users to register credentials on multiple devices as the primary recovery method. Recovery credentials provide a fallback when that’s not possible. Users can register multiple recovery credentials. One is typically created during initial registration, and more can be added later via the Create Credential flow.
Users should always have at least one recovery credential available. Generate a recovery credential for your users during registration, and when a recovery credential is used (which invalidates all existing credentials), generate a new one as part of the recovery flow. This way users are never left without a recovery path.
Nudge users to register a second credential. Consider prompting users to add a backup credential right after their initial registration, and showing a persistent security banner in your app until they do. End users who lose their only credential and have no recovery key will need you to initiate a delegated recovery on their behalf. Proactive nudges reduce that support burden.
You could store recovery credentials server-side and release them after identity verification (KYC, etc.), but this is not recommended. Whoever controls the decryption password can take control of the wallet, which undermines the delegated signing model.

How recovery credentials work

A RecoveryKey credential uses an encryptedPrivateKey field - an opaque string that DFNS stores and returns to you. You implement the encryption, and the user keeps the decryption password.
DFNS stores the encrypted blob but never has access to the decryption password. Only the user can decrypt and use the recovery key.
When used, a recovery credential triggers the recovery flow which invalidates all existing credentials for security.

Implementing user-held recovery

If implementing recovery in a browser without Node.js, use the @dfns/sdk-browser package for signing operations. If you must implement manually, see Base64Url encoding for correct encoding functions.
1

Generate a recovery keypair during registration

When a user registers, generate a recovery keypair and encrypt the private key with a password. This must happen on the client side - the password should never be sent to your server.
Frontend - Recovery credential generation
2

Display the recovery password to the user

Show the recovery password to the user with clear instructions:
The user must store this password themselves. You should not store it.
3

Register the recovery credential with DFNS

Bundle the recovery credential into the same Complete User Registration (or Complete End User Registration with Wallets) call as the first passkey. The public key and encryptedPrivateKey are sent to DFNS. The password stays with the user.Which challenge to use. The RecoveryKey credential signs the same challenge returned by the registration init endpoint (Create Delegated Registration Challenge, Create Registration Challenge, or Create Social Registration Challenge). All credentials in the same registration call share that one challenge.Build the clientData for the recovery credential manually, since it is a key-style credential and not a Fido2 passkey:
Frontend - Build clientData for the RecoveryKey
See Credentials Data for the exact clientData and attestationData formatting rules. Incorrect stringification causes Unable to verify signature errors.
Frontend - Include in registration request
To add a recovery credential after registration instead, use the Create Credential flow. The challenge then comes from Create Credential Challenge (or Create Credential Challenge With Code); the rest of the construction is identical.
4

Implement the recovery flow

Your server calls Create Delegated Recovery Challenge with a service-account token to initiate recovery. This returns a temporaryAuthenticationToken, the challenge, and allowedRecoveryCredentials (which contains the encryptedPrivateKey). Pass these to the client — not your service-account token. All decryption and signing then happens on the client side.
Server - Initiate recovery
Client - Sign and complete recovery
The recovery key signs the clientData bytes, not the credential JSON. Signing JSON.stringify(newCredentials) directly produces challenge doesn't match or Invalid signature of Key credential assertion.
Encode signature as base64url — use .toString('base64url') in Node.js. Standard base64 will cause a 400 error.
5

Generate new recovery credentials

After recovery, all previous credentials (including recovery credentials) are invalidated. Always generate a new recovery credential and display the new recovery password to the user. Do not let the user leave the recovery flow without a fresh recovery credential in place.

Security considerations

  • Password strength - Generate strong random passwords. Consider using word-based formats (like BIP39) for easier transcription.
  • Clear user instructions - Users must understand the importance of storing their recovery password securely.
  • Rate limiting - Prevent brute-force attempts on recovery flows.

Account Recovery

Overview of recovery mechanisms for users.

Credentials Data

How to build Client Data and Attestation Data objects.

Create Delegated Recovery Challenge

API endpoint to initiate recovery for an end user.

Recover User

API endpoint to complete user recovery.
Last modified on June 8, 2026