Migration von Firebase Auth
Firebase Authentication ist eine beliebte Wahl für den schnellen Einstieg, aber wenn Anwendungen wachsen, benötigen Teams oft Enterprise-Features, die Firebase nicht bietet: Enterprise-SSO (SAML/OIDC), SCIM-Provisionierung, Fine-Grained Authorization, Organisationen mit B2B-Multi-Tenancy, Compliance-Zertifizierungen und selbst-gehostete Bereitstellungsoptionen.
Feature-Mapping
| Firebase-Auth-Feature | Auris-Äquivalent | Hinweise |
|---|---|---|
| E-Mail/Passwort-Login | Gehostete Login-Seiten | OAuth2-PKCE-Flow, tenant-gebrandete UI |
| Social Providers (Google, Facebook, etc.) | Social Login | 9 Anbieter, gleicher OAuth2-Flow |
| Phone Auth (SMS) | SMS OTP | Twilio-Anbieter, 2FA und passwortlos |
| Custom Claims | Custom JWT Claims | Pro-Anwendung, 5 Werttypen, admin-konfigurierbar |
| Firebase Admin SDK | Management-Client (@auris/js) | M2M-Client-Credentials, Benutzer/Rollen/Org-CRUD |
| Security Rules | FGA + RBAC | Zanzibar-Style ReBAC, leistungsfähiger als Security Rules |
| Email Link Sign-In | Magic Links | Token-basiert, Auto-Signup-Support |
| Multi-Factor Auth | Multi-Faktor-Auth | TOTP, SMS, WebAuthn (Firebase unterstützt nur SMS + TOTP) |
Features, die Auris über Firebase hinaus bietet
| Feature | Beschreibung |
|---|---|
| Enterprise-SSO | SAML 2.0 + OIDC-Verbund für Corporate IdPs |
| SCIM 2.0 Provisionierung | Automatische Benutzersynchronisierung mit Okta, Azure AD, etc. |
| Organizations B2B | Multi-Org mit Mitgliederrollen und Einladungen |
| Fine-Grained Authorization (FGA) | Zanzibar-Style beziehungsbasierte Zugriffskontrolle |
| Log Streaming | Audit-Logs zu Datadog, Splunk, S3 exportieren |
| Angriffsschutz | IP-Regeln, Brute-Force-Sperre, CAPTCHA |
Migrationsschritte
Schritt 1: Benutzer aus Firebase exportieren
// export-firebase-users.ts
import admin from 'firebase-admin'
import fs from 'fs'
admin.initializeApp({
credential: admin.credential.cert('./service-account-key.json'),
})
async function exportAllUsers() {
const users = []
let nextPageToken
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 || '',
disabled: user.disabled,
customClaims: user.customClaims,
createdAt: user.metadata.creationTime,
})
}
nextPageToken = result.pageToken
console.log(`${users.length} Benutzer exportiert...`)
} while (nextPageToken)
return users
}
exportAllUsers().then((users) => {
fs.writeFileSync('firebase-users-export.json', JSON.stringify(users, null, 2))
console.log(`Gesamt: ${users.length} Benutzer exportiert`)
})Firebase exportiert Passwort-Hashes mit einem modifizierten scrypt-Algorithmus (Firebase scrypt). Diese Hashes können nicht direkt von Auris verifiziert werden, da Auris bcrypt verwendet. Du musst die Passwort-Migration mit dem unten beschriebenen Lazy-Migration-Muster durchführen.
Schritt 2: Passwort-Hash-Migration verwalten
Option A: Lazy Migration (Empfohlen)
Das Lazy-Migration-Muster re-hashiert Passwörter transparent, wenn sich Benutzer anmelden:
- Benutzer ohne Passwörter in Auris importieren
- Wenn ein Benutzer versucht, sich bei Auris anzumelden und kein Passwort gesetzt hat, einen spezifischen Flow zurückgeben
- Deine Anwendung versucht, die Anmeldedaten gegen Firebase über das Admin SDK zu verifizieren
- Bei Firebase-Verifizierung das Passwort des Benutzers in Auris über die Admin-API setzen
- Alle nachfolgenden Logins gehen direkt durch Auris
// Middleware für Lazy-Passwort-Migration
async function lazyMigratePassword(
email: string,
password: string,
aurisManagementToken: string
): Promise<boolean> {
try {
// Schritt 1: Anmeldung bei Firebase versuchen
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
}
// Schritt 2: Firebase hat das Passwort verifiziert — in Auris setzen
const userResponse = await fetch(
`https://auth.ihrUnternehmen.com/api/users?email=${encodeURIComponent(email)}`,
{
headers: {
Authorization: `Bearer ${aurisManagementToken}`,
'x-tenant': 'ihr-tenant-id',
},
}
)
const userData = await userResponse.json()
const userId = userData.data?.[0]?.id
if (!userId) return false
// Schritt 3: Passwort in Auris setzen
await fetch(
`https://auth.ihrUnternehmen.com/api/users/${userId}/set-password`,
{
method: 'POST',
headers: {
Authorization: `Bearer ${aurisManagementToken}`,
'x-tenant': 'ihr-tenant-id',
'Content-Type': 'application/json',
},
body: JSON.stringify({ password }),
}
)
console.log(`Passwort migriert für Benutzer: ${email}`)
return true
} catch (error) {
console.error(`Passwort-Migration fehlgeschlagen für ${email}:`, error)
return false
}
}Option B: Passwort-Reset erzwingen (Einfacher)
- Benutzer ohne Passwörter importieren
- Nach dem Import Passwort-Reset-E-Mails für alle Benutzer auslösen
- Benutzer setzen ein neues Passwort beim ersten Login
Schritt 3: Benutzer in Auris importieren
// transform-firebase-users.ts
import fs from 'fs'
const firebaseUsers = JSON.parse(
fs.readFileSync('firebase-users-export.json', 'utf-8')
)
const aurisUsers = firebaseUsers
.filter((u) => u.email && !u.disabled)
.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(`${aurisUsers.length} Benutzer für Import transformiert`)Schritt 4: Anwendung in der Auris-Console erstellen
- Anwendungen → Anwendung erstellen öffnen
- WEB als Anwendungstyp auswählen
- Callback-URLs hinzufügen (dieselben wie bei Firebase)
- Client-ID notieren
Schritt 5: Firebase-SDK durch Auris-SDK ersetzen
# Firebase entfernen
npm uninstall firebase firebase-admin
# Auris installieren
npm install @auris/js @auris/reactSchritt 6: Anwendungscode aktualisieren
Initialisierung:
// VORHER (Firebase)
import { initializeApp } from 'firebase/app'
import { getAuth } from 'firebase/auth'
const app = initializeApp({ apiKey: 'AIza...', authDomain: 'myapp.firebaseapp.com' })
const auth = getAuth(app)
// NACHHER (Auris)
import { AurisClient } from '@auris/js'
const auris = new AurisClient({
domain: 'auth.ihrUnternehmen.com',
clientId: 'ihr-client-id',
redirectUri: 'http://localhost:3000/callback',
autoRefresh: true,
})ID-Token für API-Aufrufe:
// VORHER (Firebase)
const token = await auth.currentUser?.getIdToken()
// NACHHER (Auris)
const token = await auris.getAccessToken()
// Der Rest deines API-Aufruf-Codes bleibt gleich
const response = await fetch('/api/protected', {
headers: { Authorization: `Bearer ${token}` },
})Serverseitige Token-Verifizierung:
// VORHER (Firebase Admin SDK)
import admin from 'firebase-admin'
const decoded = await admin.auth().verifyIdToken(token)
// NACHHER (Auris — mit JWKS)
import { verifyJwt } from '@auris/js/jwt-verify'
async function verifyToken(token: string) {
const decoded = await verifyJwt(token, {
jwksUrl: 'https://auth.ihrUnternehmen.com/.well-known/jwks.json',
})
return decoded
}Schritt 7: Custom Claims migrieren
Firebase Custom Claims werden typischerweise über das Admin SDK gesetzt:
// VORHER (Firebase)
await admin.auth().setCustomUserClaims(uid, { role: 'admin', plan: 'enterprise' })In Auris werden Custom Claims per Anwendung in der Console konfiguriert (Anwendungen → [App] → Custom-Claims-Reiter).
Schritt 8: Security Rules zu FGA migrieren
Firebase Security Rules Beispiel:
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;
}
}
}Auris FGA-äquivalentes Modell:
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: editorZugriff in deiner Anwendung prüfen:
import { AurisClient } from '@auris/js'
const result = await auris.fga.check({
objectType: 'document',
objectId: 'doc_123',
relation: 'can_read',
subjectType: 'user',
subjectId: 'usr_abc',
})
if (result.allowed) {
// Benutzer kann das Dokument lesen
}Migrations-Zeitplan
| Woche | Aktivitäten |
|---|---|
| 1 | Auris-Tenant einrichten, Anwendungen erstellen, Social Provider konfigurieren, Firebase-Benutzer exportieren |
| 2 | Benutzer in Auris importieren, Lazy-Passwort-Migrations-Endpunkt implementieren, FGA-Modell einrichten |
| 3 | Firebase-SDK durch Auris-SDK ersetzen, alle Auth-Flows testen |
| 4 | Staging-Bereitstellung und QA, Custom Claims migrieren, Webhooks/Log-Streaming einrichten |
| 5 | Produktionsbereitstellung, Lazy-Migration-Fortschritt überwachen |
| 6–8 | Migrationsabschlussrate überwachen, Passwort-Reset an verbleibende Benutzer senden |
| 8+ | Firebase-Projekt außer Betrieb nehmen |
Post-Migration-Checkliste
- Alle Benutzer können sich anmelden (E-Mail/Passwort, Social)
- Lazy-Passwort-Migration funktioniert
- Custom Claims erscheinen in Access Tokens
- FGA-Autorisierungsprüfungen geben korrekte Ergebnisse zurück
- Serverseitige Token-Verifizierung verwendet Auris-JWKS
- Firebase-SDK ist vollständig aus der Codebase entfernt
Halte dein Firebase-Projekt während der Lazy-Migration-Periode aktiv. Überwache den Prozentsatz der Benutzer, die ihre Passwörter migriert haben, indem du Auris-Audit-Logs auf user.password_changed-Ereignisse überprüfst.
Verwandte Leitfäden
- Gehostetes Login (PKCE) — Login-Flow implementieren
- Custom JWT Claims — Firebase Custom Claims ersetzen
- Fine-Grained Authorization — Firebase Security Rules ersetzen
- Social Login — OAuth2-Anbieter konfigurieren
- Benutzer-Import/Export — Massen-Benutzermigration