Skip to content

Migrating from Auth0

This guide walks you through migrating from Auth0 to Skycloak, including users, applications, and authentication flows.

  • Cost Savings: Transparent pricing without per-MAU charges
  • Open Source: Built on Keycloak, avoiding vendor lock-in
  • Full Control: Complete access to all features and configurations
  • Better Performance: Dedicated clusters for your workload
  • EU Data Residency: Available for compliance requirements

The migration process involves:

  1. Setting up your Skycloak cluster
  2. Migrating applications and configurations
  3. Exporting and importing users
  4. Updating your application code
  5. Testing and verification
  6. Switching over production traffic

Estimated Timeline: 2-5 days depending on complexity

  1. Sign up for Skycloak
  2. Create a production cluster:
    • Choose a location close to your users
    • Select appropriate size based on your Auth0 usage
    • Enable high availability for production

Match your Auth0 tenant settings:

# Realm Settings
Login Theme: Match Auth0 Universal Login
Token Lifespan:
  Access Token: 300s (5 minutes)
  Refresh Token: 2592000s (30 days)
Session Idle: 1800s (30 minutes)

Map Auth0 Applications to Keycloak Clients

Section titled “Map Auth0 Applications to Keycloak Clients”
Auth0 Keycloak Notes
Single Page Application Public Client Enable PKCE
Regular Web Application Confidential Client Uses client secret
Machine to Machine Service Account Client credentials flow
Native Application Public Client Mobile/desktop apps

Use Auth0 Management API to export:

# Get all applications
curl -X GET "https://YOUR_DOMAIN.auth0.com/api/v2/clients" \
  -H "Authorization: Bearer YOUR_MGMT_TOKEN" > auth0-apps.json

For each Auth0 application, create a Keycloak client:

// Example: SPA Migration
const auth0App = {
  name: 'My React App',
  app_type: 'spa',
  callbacks: ['http://localhost:3000/callback'],
  allowed_origins: ['http://localhost:3000'],
  allowed_logout_urls: ['http://localhost:3000'],
};

// Keycloak equivalent
const keycloakClient = {
  clientId: 'my-react-app',
  name: 'My React App',
  publicClient: true,
  redirectUris: ['http://localhost:3000/callback'],
  webOrigins: ['http://localhost:3000'],
  attributes: {
    'pkce.code.challenge.method': 'S256',
  },
};

Use Auth0 export extension or Management API:

# Export users (paginated)
curl -X GET "https://YOUR_DOMAIN.auth0.com/api/v2/users?per_page=100&page=0" \
  -H "Authorization: Bearer YOUR_MGMT_TOKEN" > users-page-0.json

Map Auth0 user structure to Keycloak format:

function transformUser(auth0User) {
  return {
    username: auth0User.email || auth0User.user_id,
    email: auth0User.email,
    emailVerified: auth0User.email_verified,
    enabled: !auth0User.blocked,
    firstName: auth0User.given_name,
    lastName: auth0User.family_name,
    attributes: {
      auth0_user_id: auth0User.user_id,
      picture: auth0User.picture,
      // Preserve custom attributes
      ...auth0User.user_metadata,
    },
    credentials: [
      {
        type: 'password',
        temporary: false,
        // Password migration handled separately
      },
    ],
  };
}

Use Keycloak Admin API:

const axios = require('axios');

async function importUsers(users, accessToken) {
  const keycloakUrl = 'https://your-cluster-id.app.skycloak.io/admin/realms/master/users';

  for (const user of users) {
    try {
      await axios.post(keycloakUrl, user, {
        headers: {
          Authorization: `Bearer ${accessToken}`,
          'Content-Type': 'application/json',
        },
      });
      console.log(`Imported user: ${user.email}`);
    } catch (error) {
      console.error(`Failed to import ${user.email}:`, error.response.data);
    }
  }
}
  • Simplest approach
  • Send password reset emails to all users
  • Good for smaller user bases
  • Keep Auth0 active temporarily
  • Migrate passwords on first login
  • Implement custom authenticator in Keycloak
  • If you have password hashes
  • Implement custom password hash provider
  • Seamless user experience
// React with Auth0
import { Auth0Provider, useAuth0 } from '@auth0/auth0-react';

<Auth0Provider
  domain="YOUR_DOMAIN.auth0.com"
  clientId="YOUR_CLIENT_ID"
  redirectUri={window.location.origin}
>
  <App />
</Auth0Provider>;

// Using auth
const { loginWithRedirect, logout, user, isAuthenticated } = useAuth0();
// React with Keycloak
import { AuthProvider, useAuth } from 'react-oidc-context';

const oidcConfig = {
  authority: 'https://your-cluster-id.app.skycloak.io/realms/master',
  client_id: 'your-client-id',
  redirect_uri: window.location.origin,
  scope: 'openid profile email',
};

<AuthProvider {...oidcConfig}>
  <App />
</AuthProvider>;

// Using auth
const { signinRedirect, signoutRedirect, user, isAuthenticated } = useAuth();

Update your backend to validate Keycloak tokens:

// Before: Auth0
const { auth } = require('express-oauth2-jwt-bearer');
const checkJwt = auth({
  audience: 'YOUR_API_IDENTIFIER',
  issuerBaseURL: 'https://YOUR_DOMAIN.auth0.com/',
});

// After: Keycloak
const jwt = require('express-jwt');
const jwksRsa = require('jwks-rsa');

const checkJwt = jwt({
  secret: jwksRsa.expressJwtSecret({
    cache: true,
    rateLimit: true,
    jwksRequestsPerMinute: 5,
    jwksUri: 'https://your-cluster-id.app.skycloak.io/realms/master/protocol/openid-connect/certs',
  }),
  audience: 'your-client-id',
  issuer: 'https://your-cluster-id.app.skycloak.io/realms/master',
  algorithms: ['RS256'],
});
  1. Export Auth0 Universal Login customizations
  2. Create custom Keycloak theme
  3. Apply branding in Skycloak dashboard
Auth0 Feature Keycloak Equivalent
Rules Authentication Scripts / Custom Authenticators
Hooks Event Listeners
Actions Authentication Flow Steps
Connections Identity Providers

Configure social providers in Keycloak:

Google:
  Client ID: your-google-client-id
  Client Secret: your-google-secret

GitHub:
  Client ID: your-github-client-id
  Client Secret: your-github-secret
  • User login with existing credentials
  • Social login providers
  • Password reset flow
  • MFA/2FA if enabled
  • API authentication
  • User profile updates
  • Admin operations

Run both systems in parallel:

  1. Update applications to support both providers
  2. Use feature flags to control routing
  3. Gradually migrate traffic
  4. Monitor error rates
// Feature flag approach
const authProvider = featureFlags.useKeycloak ? keycloakConfig : auth0Config;
  • All users migrated
  • Applications updated and tested
  • DNS entries prepared
  • Monitoring configured
  • Rollback plan ready
  1. Enable maintenance mode (optional)
  2. Final user sync from Auth0
  3. Update DNS/configuration to point to Keycloak
  4. Monitor closely for first 24 hours
  5. Keep Auth0 data for 30 days as backup
  • Monitor authentication metrics
  • Gather user feedback
  • Optimize performance
  • Document new processes

Solution: Map Auth0 claims to Keycloak:

// Add protocol mapper in Keycloak
{
  name: "auth0_user_id",
  protocol: "openid-connect",
  protocolMapper: "oidc-usermodel-attribute-mapper",
  config: {
    "user.attribute": "auth0_user_id",
    "claim.name": "sub",
    "jsonType.label": "String"
  }
}

Solution: Configure proper web origins in Keycloak client settings

Solution: Adjust Keycloak session settings to match Auth0 behavior

Skycloak does not currently provide an automated migration toolkit for Auth0. Use the manual export/transform/import steps described above (Step 2: Migrate Applications, Step 3: Migrate Users) to move your applications and users.

After successful migration:

  1. Configure custom branding
  2. Set up monitoring
  3. Implement advanced features
  4. Optimize performance

Welcome to Skycloak! 🎉