The Invisible Identity Transplant: Unpacking descope-migration

How a Python utility reconstructs legacy password hashes and auto-discovers schemas to move user bases without forcing a single password reset.

6 min read · descope/descope-migration

A bonsai tree root system being transplanted by mechanical arms into a glass terrarium. This illustrates the delicate process of moving complex identity data without breaking relationships.
Migrating identity data requires surgical precision to preserve user relationships and credentials.
Key Takeaways

The Gravity of Identity Data

User data has immense gravity. Moving a user base from a legacy Identity Provider usually results in a chaotic cascade of forced global password resets, massive churn, and a flooded support queue. Standard CSV exports are blunt instruments. They destroy the nuanced relationships between users, roles, and custom attributes.

The descope-migration repository offers a different approach. It is a Python utility built on the philosophy of migration-as-code. Instead of relying on static file dumps, it interfaces directly with legacy APIs to extract, translate, and inject identity data with structural integrity intact.

Whether you are modernizing a legacy platform, moving from another authentication vendor, or consolidating multiple identity providers, the goal is to make the change invisible to your users while keeping access uninterrupted.

Reconstructing the Hash

The most dangerous phase of any identity transition is the password migration. Most modern systems use proprietary hashing algorithms. The src/firebase_migration.py module demonstrates how this utility circumvents the forced reset problem entirely.

Instead of attempting to crack or blindly copy the hash, the tool extracts the exact cryptographic parameters from Firebase. It pulls the signer_key, salt_separator, and rounds. It then maps these parameters directly into Descope's SDK, specifically utilizing the UserPasswordFirebase class, to recreate the precise cryptographic environment for the legacy hash.

The pipeline translates proprietary legacy hashes into the new system without exposing plaintext passwords.

Schema Auto-Discovery

Manual schema mapping is notoriously error-prone. The cognito_migration.py module eliminates this step through auto-discovery. It does not rely on static mapping files.

The tool queries the AWS User Pool directly. It identifies custom attributes, typically prefixed with custom:, and dynamically maps their primitive types. It then provisions the target Descope environment on the fly, ensuring the new schema perfectly reflects the old one before a single user record is moved.

A vintage pantograph mapping device scanning disorganized geometric blocks and carving organized matching slots into a stone tablet. This represents automated schema discovery and mapping.
Schema auto-discovery reads the legacy environment and automatically provisions the target architecture.

The Migration-as-Code Template

Architecturally, the repository is designed as a template rather than an opaque black box. The src/main.py dispatcher routes execution to heavily isolated provider logic. This ensures the unique API quirks of Auth0 do not contaminate the Cognito pipeline.

Operational safety is baked into the core utilities. The required --dry-run flag allows teams to validate state transitions before committing writes. Meanwhile, an automated exponential backoff mechanism elegantly absorbs the inevitable rate limits and timeouts associated with legacy cloud APIs.

FeatureTraditional CSV Migrationdescope-migration Utility
Data ExtractionFlat file exportPaginated API aggregation
PasswordsForced global resetCryptographic hash reconstruction
Schema MappingManual spreadsheet matchingAutomated dynamic discovery
ValidationBlind importState validation via dry runs
Failure HandlingManual retry of failed rowsAutomated exponential backoff