Skip to Content

Migrar desde Firebase Auth

Firebase Authentication es una opción popular para empezar rápidamente, pero a medida que las aplicaciones crecen, los equipos suelen necesitar funcionalidades empresariales que Firebase no ofrece: SSO empresarial (SAML/OIDC), aprovisionamiento SCIM, autorización detallada, organizaciones con multi-tenancy B2B, certificaciones de cumplimiento y opciones de despliegue auto-alojado. Auris proporciona todo esto manteniendo la experiencia de desarrollo de Firebase Auth.

Esta guía explica cómo exportar usuarios desde Firebase, gestionar la transición de hashes de contraseñas, reemplazar el SDK de Firebase por el de Auris, y migrar custom claims y reglas de seguridad.

Mapeo de Funcionalidades

| Funcionalidad de Firebase Auth | Equivalente en Auris | Notas |

|-------------------------------|---------------------|-------|

| Email/Contraseña | Páginas de Inicio de Sesión Alojadas | Flujo OAuth2 PKCE, interfaz con marca del tenant |

| Proveedores Sociales (Google, Facebook, etc.) | Inicio de Sesión Social | 9 proveedores, mismo flujo OAuth2 |

| Auth por Teléfono (SMS) | SMS OTP | Proveedor Twilio, 2FA y sin contraseña |

| Auth Anónima | No disponible | Usa magic links para un onboarding sin fricción |

| Custom Claims | Custom JWT Claims | Por aplicación, 5 tipos de valor, configurable por admin |

| Firebase Admin SDK | Cliente de Gestión (@auris/js) | Credenciales de cliente M2M, CRUD de usuarios/roles/orgs |

| Security Rules | FGA (Autorización Detallada) + RBAC | ReBAC estilo Zanzibar, más potente que Security Rules |

| Email Link Sign-In | Magic Links | Basado en token, soporte de registro automático |

| Autenticación Multifactor | Autenticación Multifactor | TOTP, SMS, WebAuthn (Firebase solo admite SMS + TOTP) |

| Firebase UI | Páginas de Inicio de Sesión Alojadas | Totalmente gestionadas, marca personalizable |

| Gestión de Usuarios (Consola) | Consola de Auris | Consola de administración completa con roles, permisos y sesiones |

| Verificación de ID Token | Verificación JWT (JWKS) | RS256 con endpoint JWKS, verificador @auris/js |

| Blocking Functions | Motor de Acciones | 6 puntos de activación, JS en sandbox, editor visual |

Funcionalidades que Auris Añade Respecto a Firebase

| Funcionalidad | Descripción |

|---------------|-------------|

| SSO Empresarial | Federación SAML 2.0 + OIDC para IdPs corporativos |

| Aprovisionamiento SCIM 2.0 | Sincronización automática de usuarios con Okta, Azure AD, etc. |

| Organizaciones B2B | Multi-org con roles de miembro e invitaciones |

| Autorización Detallada (FGA) | Control de acceso basado en relaciones estilo Zanzibar |

| Roles y Permisos | RBAC tri-estado con alcance por aplicación |

| Dominios Personalizados | Páginas de autenticación white-label bajo tu dominio |

| Transmisión de Logs | Exporta logs de auditoría a Datadog, Splunk, S3 |

| Webhooks | Notificaciones de eventos en tiempo real firmadas con HMAC |

| Limitación de Tasa | Limitación de tasa por niveles con cabeceras estándar |

| Protección Contra Ataques | Reglas de IP, bloqueo por fuerza bruta, CAPTCHA, detección de inicio de sesión sospechoso |

Pasos de Migración

Paso 1: Exportar Usuarios desde Firebase

Usa el Firebase Admin SDK para exportar todos los usuarios. Firebase proporciona un método listUsers que pagina por todos los usuarios:

// export-firebase-users.ts import admin from 'firebase-admin' import fs from 'fs' admin.initializeApp({ credential: admin.credential.cert('./service-account-key.json'), }) interface ExportedUser { uid: string email: string emailVerified: boolean displayName: string phoneNumber?: string disabled: boolean customClaims?: Record<string, unknown> passwordHash?: string passwordSalt?: string providerData: Array<{ providerId: string; uid: string }> createdAt: string } async function exportAllUsers(): Promise<ExportedUser[]> { const users: ExportedUser[] = [] let nextPageToken: string | undefined do { const result = await admin.auth().listUsers(1000, nextPageToken) for (const user of result.users) { users.push({ uid: user.uid, email: user.email || '', emailVerified: user.emailVerified, displayName: user.displayName || '', phoneNumber: user.phoneNumber, disabled: user.disabled, customClaims: user.customClaims, passwordHash: user.passwordHash, passwordSalt: user.passwordSalt, providerData: user.providerData.map((p) => ({ providerId: p.providerId, uid: p.uid, })), createdAt: user.metadata.creationTime, }) } nextPageToken = result.pageToken console.log(`Exportados ${users.length} usuarios...`) } while (nextPageToken) return users } exportAllUsers().then((users) => { fs.writeFileSync('firebase-users-export.json', JSON.stringify(users, null, 2)) console.log(`Total: ${users.length} usuarios exportados`) })

Firebase exporta los hashes de contraseñas usando un algoritmo scrypt modificado (Firebase scrypt). Estos hashes no pueden verificarse directamente en Auris, ya que Auris usa bcrypt. Deberás gestionar la migración de contraseñas usando el patrón de migración diferida descrito a continuación.

Paso 2: Gestionar la Migración de Hashes de Contraseñas

Firebase usa una variante personalizada de scrypt para el hash de contraseñas que no es compatible con el bcrypt estándar que usa Auris. Existen dos enfoques:

Opción A: Migración Diferida (Recomendada)

El patrón de migración diferida vuelve a hashear las contraseñas de forma transparente a medida que los usuarios inician sesión. Proporciona cero fricción para los usuarios finales.

Cómo funciona:

  1. Importa usuarios en Auris sin contraseñas (se crearán como cuentas sin contraseña)

  2. Cuando un usuario intente iniciar sesión en Auris y no tenga contraseña configurada, devuelve un flujo específico

  3. Tu aplicación intenta verificar la credencial contra Firebase usando el Admin SDK

  4. Si Firebase verifica con éxito, configura la contraseña del usuario en Auris vía la API de Administración

  5. Los inicios de sesión posteriores van directamente a través de Auris

// Middleware para migración diferida de contraseñas // Esto se ejecuta en tu backend, no en Auris import admin from 'firebase-admin' async function lazyMigratePassword( email: string, password: string, aurisManagementToken: string ): Promise<boolean> { try { // Paso 1: Intentar iniciar sesión con Firebase // Nota: Firebase Admin SDK no tiene signInWithPassword // Usa la Firebase Auth REST API en su lugar const firebaseResponse = await fetch( `https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=${process.env.FIREBASE_API_KEY}`, { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ email, password, returnSecureToken: false, }), } ) if (!firebaseResponse.ok) { return false // Credenciales inválidas también en Firebase } // Paso 2: Firebase verificó la contraseña — configurarla en Auris // Buscar el usuario en Auris por correo const userResponse = await fetch( `https://auth.tuempresa.com/api/users?email=${encodeURIComponent(email)}`, { headers: { Authorization: `Bearer ${aurisManagementToken}`, 'x-tenant': 'your-tenant-id', }, } ) const userData = await userResponse.json() const userId = userData.data?.[0]?.id if (!userId) return false // Paso 3: Establecer la contraseña en Auris await fetch( `https://auth.tuempresa.com/api/users/${userId}/set-password`, { method: 'POST', headers: { Authorization: `Bearer ${aurisManagementToken}`, 'x-tenant': 'your-tenant-id', 'Content-Type': 'application/json', }, body: JSON.stringify({ password }), } ) console.log(`Contraseña migrada para el usuario: ${email}`) return true } catch (error) { console.error(`La migración de contraseña falló para ${email}:`, error) return false } }

Opción B: Forzar Restablecimiento de Contraseña (Más Sencillo)

Si prefieres una ruptura limpia con Firebase:

  1. Importa usuarios sin contraseñas

  2. Tras la importación, activa correos de restablecimiento de contraseña para todos los usuarios

  3. Los usuarios establecen una nueva contraseña en su primer inicio de sesión

Esto es más sencillo de implementar, pero requiere que todos los usuarios tomen medidas.

Paso 3: Importar Usuarios en Auris

Transforma la exportación de Firebase al formato de importación de Auris:

// transform-firebase-users.ts import fs from 'fs' interface FirebaseUser { uid: string email: string emailVerified: boolean displayName: string phoneNumber?: string disabled: boolean customClaims?: Record<string, unknown> } interface AurisImportUser { email: string firstName: string lastName: string emailVerified: boolean } const firebaseUsers: FirebaseUser[] = JSON.parse( fs.readFileSync('firebase-users-export.json', 'utf-8') ) const aurisUsers: AurisImportUser[] = firebaseUsers .filter((u) => u.email && !u.disabled) // Omitir usuarios deshabilitados y sin correo .map((user) => { const nameParts = (user.displayName || '').split(' ') return { email: user.email, firstName: nameParts[0] || '', lastName: nameParts.slice(1).join(' ') || '', emailVerified: user.emailVerified, } }) fs.writeFileSync('auris-import.json', JSON.stringify(aurisUsers, null, 2)) console.log(`Se transformaron ${aurisUsers.length} usuarios para importar`)

Subir a Auris:

curl -X POST https://auth.tuempresa.com/api/users/import \ -H "Authorization: Bearer $AURIS_ACCESS_TOKEN" \ -H "x-tenant: your-tenant-id" \ -F "[email protected]" \ -F "format=json"

Paso 4: Crear una Aplicación en la Consola de Auris

  1. Abre la Consola de Auris y ve a Aplicaciones → Crear Aplicación

  2. Selecciona WEB como tipo de aplicación

  3. Introduce el nombre de tu aplicación

  4. Añade tus URLs de Callback (las mismas que usabas con Firebase)

  5. Añade tus Orígenes Permitidos

  6. Guarda y anota el Client ID

Paso 5: Reemplazar el SDK de Firebase por el SDK de Auris

# Eliminar Firebase npm uninstall firebase firebase-admin # Instalar Auris npm install @auris/js @auris/react # Para Next.js: npm install @auris/nextjs

Paso 6: Actualizar el Código de la Aplicación

Inicialización:

// ANTES (Firebase) import { initializeApp } from 'firebase/app' import { getAuth, signInWithEmailAndPassword, signOut, onAuthStateChanged } from 'firebase/auth' const app = initializeApp({ apiKey: 'AIza...', authDomain: 'myapp.firebaseapp.com', projectId: 'myapp', }) const auth = getAuth(app) // DESPUÉS (Auris) import { AurisClient } from '@auris/js' const auris = new AurisClient({ domain: 'auth.tuempresa.com', clientId: 'your-client-id', redirectUri: 'http://localhost:3000/callback', autoRefresh: true, })

Autenticación (React):

// ANTES (Firebase) import { getAuth, signInWithEmailAndPassword, signOut } from 'firebase/auth' import { useAuthState } from 'react-firebase-hooks/auth' function Login() { const auth = getAuth() const [user, loading] = useAuthState(auth) const handleLogin = () => { signInWithEmailAndPassword(auth, email, password) } const handleLogout = () => { signOut(auth) } if (loading) return <p>Cargando...</p> if (user) return <button onClick={handleLogout}>Cerrar sesión</button> return <button onClick={handleLogin}>Iniciar sesión</button> } // DESPUÉS (Auris) import { AurisProvider, useAuris } from '@auris/react' function App() { return ( <AurisProvider domain="auth.tuempresa.com" clientId="your-client-id" redirectUri={window.location.origin + '/callback'} > <Login /> </AurisProvider> ) } function Login() { const { loginWithRedirect, logout, user, isAuthenticated, isLoading } = useAuris() if (isLoading) return <p>Cargando...</p> if (isAuthenticated) { return ( <button onClick={() => logout({ returnTo: window.location.origin })}> Cerrar sesión </button> ) } return <button onClick={loginWithRedirect}>Iniciar sesión</button> }

Obtener el Usuario Actual:

// ANTES (Firebase) import { getAuth, onAuthStateChanged } from 'firebase/auth' const auth = getAuth() onAuthStateChanged(auth, (user) => { if (user) { console.log('Usuario:', user.uid, user.email) } }) // DESPUÉS (Auris) const user = await auris.getUser() if (user) { console.log('Usuario:', user.id, user.email) } // O con el listener de cambio de estado de autenticación: auris.onAuthStateChange((user) => { if (user) { console.log('Usuario:', user.id, user.email) } })

ID Token para Llamadas a la API:

// ANTES (Firebase) import { getAuth } from 'firebase/auth' const auth = getAuth() const token = await auth.currentUser?.getIdToken() const response = await fetch('/api/protected', { headers: { Authorization: `Bearer ${token}` }, }) // DESPUÉS (Auris) const token = await auris.getAccessToken() const response = await fetch('/api/protected', { headers: { Authorization: `Bearer ${token}` }, })

Verificación de Token del Lado del Servidor:

// ANTES (Firebase Admin SDK) import admin from 'firebase-admin' async function verifyToken(token: string) { const decoded = await admin.auth().verifyIdToken(token) return decoded // { uid, email, ... } } // DESPUÉS (Auris — usando JWKS) import { verifyJwt } from '@auris/js/jwt-verify' async function verifyToken(token: string) { const decoded = await verifyJwt(token, { jwksUrl: 'https://auth.tuempresa.com/.well-known/jwks.json', }) return decoded // { sub, email, roles, ... } } // O usando el helper de Next.js: import { getSession } from '@auris/nextjs/server' export async function GET(req: Request) { const session = await getSession() if (!session) { return Response.json({ error: 'No autorizado' }, { status: 401 }) } return Response.json({ userId: session.user.id }) }

Inicio de Sesión Social (Google):

// ANTES (Firebase) import { getAuth, signInWithPopup, GoogleAuthProvider } from 'firebase/auth' const auth = getAuth() const provider = new GoogleAuthProvider() const result = await signInWithPopup(auth, provider) // DESPUÉS (Auris) // El inicio de sesión social se gestiona en la página de Inicio de Sesión Alojada — no se requieren cambios de código. // Configura Google como proveedor social en Consola → Autenticación → Inicio de Sesión Social. // Los usuarios ven el botón de Google en la página de inicio de sesión alojada automáticamente. // Si quieres ir directamente a Google: await auris.loginWithRedirect({ connection: 'google' })

Paso 7: Migrar Custom Claims

Los custom claims de Firebase se establecen normalmente vía el Admin SDK:

// ANTES (Firebase) await admin.auth().setCustomUserClaims(uid, { role: 'admin', plan: 'enterprise', orgId: 'org_123', })

En Auris, los custom claims se configuran por aplicación en la Consola:

  1. Ve a Aplicaciones → selecciona tu app → pestaña Custom Claims

  2. Añade claims:

    • role con tipo Atributo de Usuario mapeado a roles[0].name

    • plan con tipo Estático valor enterprise (o Expresión para valores dinámicos)

    • orgId con tipo Atributo de Usuario mapeado a metadata.orgId

O mediante la API:

curl -X POST https://auth.tuempresa.com/api/applications/ID_APP/custom-claims \ -H "Authorization: Bearer $AURIS_ACCESS_TOKEN" \ -H "x-tenant: your-tenant-id" \ -H "Content-Type: application/json" \ -d '{ "claimKey": "role", "valueType": "USER_ATTRIBUTE", "userAttribute": "roles", "isActive": true }'

Consulta la guía de Custom JWT Claims para la referencia completa de configuración.

Paso 8: Migrar Security Rules a FGA

Las Firebase Security Rules son reglas de control de acceso declarativas vinculadas a las rutas de Firestore o Realtime Database. Auris usa Autorización Detallada (FGA) basada en el modelo Zanzibar, que es más potente y está desacoplada de tu capa de datos.

Ejemplo de Firebase Security Rules:

rules_version = '2'; service cloud.firestore { match /databases/{database}/documents { match /documents/{docId} { allow read: if request.auth != null && (resource.data.ownerId == request.auth.uid || request.auth.uid in resource.data.viewers); allow write: if request.auth != null && resource.data.ownerId == request.auth.uid; } } }

Modelo FGA equivalente en Auris:

model schema 1.1 type user type document relations define owner: [user] define viewer: [user] or owner define editor: [user] or owner define can_read: viewer define can_write: editor

Escribe tuplas de relación para representar los datos:

# Conceder propiedad curl -X POST https://auth.tuempresa.com/api/fga/tuples \ -H "Authorization: Bearer $AURIS_ACCESS_TOKEN" \ -H "x-tenant: your-tenant-id" \ -H "Content-Type: application/json" \ -d '{ "objectType": "document", "objectId": "doc_123", "relation": "owner", "subjectType": "user", "subjectId": "usr_abc" }' # Conceder acceso de visualizador curl -X POST https://auth.tuempresa.com/api/fga/tuples \ -H "Authorization: Bearer $AURIS_ACCESS_TOKEN" \ -H "x-tenant: your-tenant-id" \ -H "Content-Type: application/json" \ -d '{ "objectType": "document", "objectId": "doc_123", "relation": "viewer", "subjectType": "user", "subjectId": "usr_xyz" }'

Comprueba el acceso en tu aplicación:

// Usando el SDK de Auris import { AurisClient } from '@auris/js' const auris = new AurisClient({ domain: 'auth.tuempresa.com', clientId: 'your-client-id', }) const result = await auris.fga.check({ objectType: 'document', objectId: 'doc_123', relation: 'can_read', subjectType: 'user', subjectId: 'usr_abc', }) if (result.allowed) { // El usuario puede leer el documento }

Consulta la guía de Autorización Detallada para la referencia completa de FGA.

Cronograma de Migración

Una migración típica de Firebase a Auris sigue este cronograma:

| Semana | Actividades |

|--------|-------------|

| 1 | Configurar tenant de Auris, crear aplicaciones, configurar proveedores sociales, exportar usuarios de Firebase |

| 2 | Importar usuarios en Auris, implementar endpoint de migración diferida de contraseñas, configurar el modelo FGA |

| 3 | Reemplazar el SDK de Firebase por el de Auris en tu aplicación, probar todos los flujos de autenticación |

| 4 | Despliegue en staging y QA, migrar custom claims, configurar webhooks/transmisión de logs |

| 5 | Despliegue en producción, monitorizar el progreso de la migración diferida, comenzar la desactivación de Firebase |

| 6-8 | Monitorizar la tasa de finalización de la migración, enviar restablecimiento de contraseña a los usuarios restantes no migrados |

| 8+ | Desactivar el proyecto de Firebase |

Lista de Verificación Post-Migración

  • Todos los usuarios pueden iniciar sesión (correo/contraseña, social, teléfono)

  • La migración diferida de contraseñas está funcionando (comprobar logs de auditoría de Auris)

  • Los custom claims aparecen en los tokens de acceso

  • Las comprobaciones de autorización FGA devuelven resultados correctos

  • La verificación de tokens del lado del servidor usa JWKS de Auris

  • Los proveedores de inicio de sesión social (Google, Facebook, etc.) están configurados

  • Los eventos de webhook se están entregando

  • El SDK de Firebase está completamente eliminado del código base

  • Las referencias al emulador de Firebase Auth se eliminaron de las pruebas

  • La facturación del proyecto de Firebase está degradada o cancelada

Mantén tu proyecto de Firebase activo durante el período de migración diferida. Monitoriza el porcentaje de usuarios que han migrado sus contraseñas comprobando los logs de auditoría de Auris para eventos user.password_changed. Una vez que la migración alcance el 95%+ de los usuarios activos, envía un correo de restablecimiento de contraseña a los usuarios restantes y programa la desactivación de Firebase.

Guías Relacionadas