Auth0 to Microsoft External ID migration playbook
A 4-6 month migration from Auth0 to Microsoft External ID — tenant setup, Action / Rule re-implementation, and traffic-shift cutover with password-hash migration.
TL;DR
Microsoft External ID consolidates the prior Azure AD B2C + Entra B2B products into a single platform. Auth0 → External ID migrations are driven by Microsoft licensing consolidation (where the org is heavily Microsoft-anchored) or by cost (Auth0 pricing at scale). Plan 4-6 months on a typical CIAM workload (1M-5M users). The harder parts are not the migration itself but (1) the Auth0 Rules / Actions you've customized, (2) the JWT issuer change for downstream APIs, and (3) the MFA re-enrollment cutover.
Auth0 (Okta Customer Identity Cloud)
Microsoft External ID
Typical timeline
4-6 months for a 1M-5M user CIAM workload with 5-15 customer-facing apps.
Why teams move
- Microsoft consolidation — already paying for E5; external identities are now in the same admin surface
- Auth0 pricing escalation at scale — External ID per-MAU pricing is often more favorable above 100K MAU
- Tighter integration with Entra workforce + Microsoft Verified ID
- Single audit surface for workforce + customer identity
The migration in 5 phases.
1. Architecture decision (Weeks 1-3)
3 weeks
- Inventory existing Auth0 tenants, applications, rules, actions, connections
- Decide External ID tenant topology (one tenant per brand vs single tenant with branding)
- Map Auth0 Organizations to External ID realms / user flows
2. External ID build + pilot (Weeks 4-12)
8 weeks
- Provision External ID tenant
- Configure user flows (sign-up, sign-in, password reset, profile edit)
- Re-implement Auth0 Rules / Actions as External ID custom policies or API connectors
- Configure social / federated identity providers
- Pilot with 1-2 lower-risk applications
3. User migration (Weeks 13-16)
4 weeks
- Bulk-export users from Auth0 (including hashed passwords if format compatible)
- Bulk-import to External ID via Microsoft Graph
- Verify user-identifier preservation (sub claim) so downstream API authorization continues to work
4. Traffic cutover (Weeks 17-20)
4 weeks
- Update application clients to use External ID OIDC endpoints
- DNS-weighted traffic shift, or per-app cutover
- Monitor login + signup success rates
- Hold at 100% External ID for 2-4 weeks before decommissioning Auth0
5. Auth0 decommission (Weeks 21-24)
4 weeks
- Final Auth0 audit-log export
- Cancel Auth0 subscription on renewal boundary
- Document the External ID operational runbook
What lives where.
| Capability | Source (Auth0) | Target (Microsoft) |
|---|---|---|
| Sign-up / sign-in flows | Auth0 Universal Login + Branding | External ID user flows + custom policies User flows cover most needs. Custom policies for advanced cases (formerly B2C IEF policies). |
| Business logic in the flow | Auth0 Rules + Actions | External ID API connectors + custom policies Rules / Actions running JavaScript at hook points → External ID API connectors calling external REST endpoints, or custom policy steps. |
| Multi-tenancy | Auth0 Organizations | External ID realms (workforce-style) or per-tenant CIAM realms Conceptually similar — discrete realms with isolated user pools. |
| MFA | Auth0 Guardian + WebAuthn + SMS | External ID built-in MFA + WebAuthn Users will need to re-enroll MFA in External ID. Plan a transition window with both available. |
| Federated / social IdP | Auth0 connections (Google, Apple, etc.) | External ID identity providers Functional equivalent. Re-configure each social IdP's OAuth client to point at External ID redirect URI. |
What moves, what doesn’t.
User records
Export Auth0 users via the Management API in batches. Import to External ID via Microsoft Graph. Preserve the Auth0 `user_id` value as External ID `extensionAttribute1` for reference.
Password hashes
Auth0 stores passwords as bcrypt; External ID accepts bcrypt on import via the import-users API. Migration preserves passwords. Document the bcrypt cost factor — External ID rehashes on next login if the factor is below its current minimum.
MFA enrollments
Not migratable across vendors. Users must re-enroll. Communicate the window 4 weeks before cutover.
Refresh tokens
All Auth0-issued refresh tokens become invalid after cutover. Users will be forced to re-authenticate on next session — time the cutover to off-peak hours.
The 7-step cutover.
- 01Pre-validate all user flows in External ID prod tenant
- 02Update client applications to use External ID OIDC endpoints (issuer, JWKS, /authorize URL)
- 03DNS-weighted shift or per-app cutover, starting with lowest-risk app
- 04Monitor login + signup success rates in 30-minute increments
- 05Hold at 100% External ID for 2-4 weeks
- 06Documented rollback: revert client OIDC config to Auth0 endpoints
What teams find out the hard way.
JWT issuer change breaks API trust
Downstream APIs are configured to trust Auth0's issuer URL. Cutover changes the issuer. Either pre-configure APIs to trust both issuers during the transition window, or coordinate API config changes with the front-end cutover (harder to coordinate).
Auth0 Rules / Actions don't port directly
JavaScript hooks in Auth0 must be re-implemented as External ID API connectors (out-of-process REST calls) or custom policies. Plan 1-2 weeks per non-trivial rule.
Custom claims namespace
Auth0's convention is namespaced custom claims (https://example.com/role). External ID has its own conventions. Map the namespace migration carefully so downstream services continue to find the claims they expect.
Branding / theming control
Auth0 has fine-grained per-tenant + per-app theming via Universal Login. External ID is more constrained. Plan UX review before commitment.
Free-tier and developer experience
Auth0's free tier and developer experience are excellent. External ID is improving but is more enterprise-focused. If a heavy chunk of your user growth comes from developer / B2D context, validate the new DX before committing.
Questions we get on this migration.
Can passwords be migrated without forcing reset?
Yes if Auth0 and External ID both use bcrypt. Hash + salt are imported as-is. Users sign in next time without resetting.
What happens to our Auth0 Actions / Rules / Hooks code?
Re-implemented as External ID API connectors (REST endpoints called by the policy) or as custom policy steps. Direct port is not possible — different execution model.
How do we handle organizations / multi-tenancy?
External ID uses realms (called "external tenants") that map functionally to Auth0 Organizations. Migration is per-realm; each realm gets its own External ID tenant or shared tenant with realm-scoped user flows.
We’ve led this migration. More than once.
Engagement starts with a 90-minute discovery call — we tell you what we’d actually do, with timeline + risk register. No commitment.