Migration Guide12 min readMarch 30, 2026

Migrating from Auth0 to Keycloak: A Step-by-Step Guide

A practical guide to migrating your identity stack from Auth0 to Keycloak. Covers user migration, social login re-linking, session continuity, and common pitfalls.

KT

KeycloakPro Team

KeycloakPro Team

Why Companies Are Leaving Auth0

Since Okta acquired Auth0 in 2021, the landscape has shifted. Pricing restructuring removed affordable tiers, the October 2023 support system breach affected all customers, and MAU-based billing has made costs unpredictable for growing companies.

If you're reading this, you've probably already decided to move. This guide will show you how to do it safely, with zero downtime and no user disruption.

Migration Overview

A successful Auth0 to Keycloak migration has four phases:

  1. Prepare — Set up Keycloak, map your Auth0 configuration
  2. Migrate Users — Export users, import into Keycloak
  3. Migrate Applications — Update your apps to point at Keycloak
  4. Cutover — Switch DNS, validate, decommission Auth0

The typical timeline is 2-4 weeks depending on complexity.

Phase 1: Prepare Your Keycloak Environment

Set Up Keycloak

Deploy Keycloak 26.x on your preferred infrastructure. For production, we recommend:

# Using Docker for local testing
docker run -p 8080:8080 \
  -e KC_BOOTSTRAP_ADMIN_USERNAME=admin \
  -e KC_BOOTSTRAP_ADMIN_PASSWORD=admin \
  quay.io/keycloak/keycloak:26.0.0 start-dev

For production, deploy on Kubernetes with PostgreSQL. See our HA Cluster guide for details.

Map Auth0 Concepts to Keycloak

Auth0 ConceptKeycloak Equivalent
TenantRealm
ApplicationClient
ConnectionIdentity Provider or User Federation
Rule / ActionAuthentication Flow / SPI
OrganizationOrganization (Keycloak 24+)
RoleRealm Role or Client Role
PermissionAuthorization Scope
Universal LoginKeycloak Theme
Custom DomainFrontend URL Configuration

Export Your Auth0 Configuration

Before migrating, document everything:

  1. Applications: List all clients, their types (SPA, Regular Web, M2M), callback URLs, and allowed origins
  2. Connections: Social providers (Google, GitHub, etc.), enterprise connections (SAML, OIDC), database connections
  3. Rules/Actions: Custom logic that runs during authentication
  4. Roles & Permissions: RBAC configuration
  5. Branding: Universal Login customization, email templates

Phase 2: Migrate Users

This is the most critical phase. Auth0 stores password hashes using bcrypt, which Keycloak supports natively.

Export Users from Auth0

Use the Auth0 Management API to export users:

# Create an export job
curl --request POST \
  --url 'https://YOUR_DOMAIN.auth0.com/api/v2/jobs/users-exports' \
  --header 'authorization: Bearer YOUR_TOKEN' \
  --header 'content-type: application/json' \
  --data '{
    "format": "json",
    "fields": [
      {"name": "user_id"},
      {"name": "email"},
      {"name": "email_verified"},
      {"name": "name"},
      {"name": "given_name"},
      {"name": "family_name"},
      {"name": "identities"},
      {"name": "created_at"},
      {"name": "last_login"}
    ]
  }'

Handle Password Hashes

Auth0 uses bcrypt for password hashing. Keycloak supports bcrypt through a credential provider. The migration script needs to:

  1. Extract the bcrypt hash from Auth0's export
  2. Create the user in Keycloak with the hash preserved
  3. Users can log in with their existing password — no reset needed
// Keycloak user representation with imported bcrypt hash
{
  "username": "user@example.com",
  "email": "user@example.com",
  "emailVerified": true,
  "enabled": true,
  "firstName": "Jane",
  "lastName": "Smith",
  "credentials": [
    {
      "type": "password",
      "credentialData": "{\"hashIterations\":10,\"algorithm\":\"bcrypt\"}",
      "secretData": "{\"value\":\"$2a$10$...the_bcrypt_hash...\"}"
    }
  ]
}

Import Users into Keycloak

Use the Keycloak Admin REST API for bulk import:

# Import a single user
curl --request POST \
  --url 'http://localhost:8080/admin/realms/YOUR_REALM/users' \
  --header 'authorization: Bearer ADMIN_TOKEN' \
  --header 'content-type: application/json' \
  --data '@user.json'

For large user bases (50,000+), use Keycloak's partial import feature or a custom migration script that batches requests and handles rate limiting.

Migrate Social Login Identities

Users who signed up via Google, GitHub, or other social providers need their identity links preserved. In Keycloak, these are called federated identity links:

# Link a social identity to an existing Keycloak user
curl --request POST \
  --url 'http://localhost:8080/admin/realms/YOUR_REALM/users/USER_ID/federated-identity/google' \
  --header 'authorization: Bearer ADMIN_TOKEN' \
  --header 'content-type: application/json' \
  --data '{
    "identityProvider": "google",
    "userId": "google-user-id-from-auth0",
    "userName": "user@gmail.com"
  }'

This ensures users who signed up with "Sign in with Google" on Auth0 can continue using Google login on Keycloak without creating a new account.

Phase 3: Migrate Applications

Update OIDC Configuration

For most applications, migration means updating the OIDC/OAuth2 configuration to point at Keycloak instead of Auth0:

Before (Auth0):

ISSUER=https://your-tenant.auth0.com/
CLIENT_ID=auth0_client_id
CLIENT_SECRET=auth0_client_secret

After (Keycloak):

ISSUER=https://keycloak.yourdomain.com/realms/your-realm
CLIENT_ID=keycloak_client_id
CLIENT_SECRET=keycloak_client_secret

Handle Token Differences

Auth0 and Keycloak tokens have different claim structures. Key differences:

ClaimAuth0Keycloak
User IDsub (auth0 pipe user_id)sub (UUID)
Emailemailemail
Roleshttps://your-ns/roles (custom)realm_access.roles
Permissionspermissions (custom)resource_access.{client}.roles
Organizationorg_idorganization (with Orgs enabled)

You'll need to update your application code to read claims from the new locations. The cleanest approach is to create a token mapper in Keycloak that adds claims in your existing format, so your application code doesn't change.

Migrate Auth0 Rules/Actions to Keycloak Flows

Auth0 Rules and Actions map to Keycloak Authentication Flows and Protocol Mappers:

  • Post-login enrichment (adding custom claims) → Protocol Mapper or Script Mapper
  • Conditional MFA → Conditional Authentication Flow
  • IP allowlisting → Custom Authenticator SPI
  • User metadata sync → Event Listener SPI

Phase 4: Cutover

The Zero-Downtime Strategy

  1. Run both systems in parallel — Keycloak handles new logins, Auth0 is still available as fallback
  2. Gradual rollout — Route 10% of traffic to Keycloak, monitor for errors, increase to 25%, 50%, 100%
  3. Session bridge — Users with active Auth0 sessions are seamlessly redirected to Keycloak on their next login
  4. DNS cutover — Once 100% of traffic is on Keycloak, update DNS and decommission Auth0

Validation Checklist

Before cutting over completely, verify:

  • All users can log in with email/password
  • Social login (Google, GitHub, etc.) works correctly
  • MFA enrollment and verification works
  • Token claims match what your applications expect
  • Session timeout and refresh token behavior is correct
  • Password reset flow works end-to-end
  • New user registration works
  • Rate limiting and brute-force protection are configured
  • Monitoring and alerting are in place

Common Pitfalls

1. Forgetting to Migrate Password Hashes

If you create users without their password hashes, every user will need to reset their password. This is the number one mistake in Auth0 migrations. Always use the bcrypt hash import method described above.

2. Breaking Social Login

Social login requires matching the external user ID exactly. If the Google user ID in Keycloak doesn't match what Auth0 stored, users will be created as new accounts. Always import federated identity links.

3. Ignoring Token Claim Differences

Your applications depend on specific token claims. Don't assume Keycloak tokens look like Auth0 tokens. Map claims explicitly using Protocol Mappers and test every application.

4. Not Testing the Rollback Plan

Always have a rollback plan. Keep Auth0 active until you're confident Keycloak is stable. A typical safe decommission timeline is 30 days after full cutover.

Timeline Estimate

PhaseDurationDependencies
Prepare Keycloak2-3 daysInfrastructure access
Migrate Users1-3 daysAuth0 Management API access
Migrate Applications3-7 daysApplication deployment access
Parallel Running1-2 weeksMonitoring in place
Full Cutover1 dayStakeholder sign-off

Total: 2-4 weeks for a typical migration with 10,000-100,000 users.

What You'll Save

For a SaaS platform with 50,000 MAU:

  • Auth0 Enterprise: ~$80,000 - $120,000/year
  • Keycloak on AWS (HA): ~$12,000 - $18,000/year
  • Annual savings: $62,000 - $108,000

That's money back in your engineering budget, every year, forever. And you own your identity infrastructure — no vendor lock-in, no surprise pricing changes, no dependency on a third party's security posture.

Need Help With Your Migration?

We've migrated dozens of companies from Auth0 to Keycloak — from startups with 5,000 users to enterprises with 500,000+. Every migration includes user import, social login re-linking, application updates, and a 30-day warranty.

Get a free migration assessment — we'll review your Auth0 setup and give you a fixed-price quote within 48 hours.

Need Help With Keycloak?

Our team specializes in production-grade Keycloak deployments. Get a free 30-minute strategy consultation.

Book a Free Strategy Call