Nutzer aus einer vorhandenen App migrieren
In diesem Dokument wird gezeigt, wie Sie Nutzer von einer vorhandenen Anwendung zu Identity Platform migrieren.
Hinweis
Admin SDK verwenden
Mit dem Admin SDK können Sie Nutzer importieren, ohne Nutzerdaten in CSV oder JSON zu exportieren. Sie können Nutzer in alle von Identity Platform unterstützten Anbieter importieren, einschließlich OAuth, SAML und OIDC.
In einem einzelnen API-Aufruf können bis zu 1.000 Nutzer importiert werden. Der Importvorgang ist für Geschwindigkeit optimiert und überprüft keine doppelten Felder. Wenn Sie einen Nutzer importieren, der mit einem vorhandenen uid
kombiniert wird, wird der vorhandene Nutzer ersetzt. Wenn Sie einen Nutzer mit einem anderen duplizierten Feld (z. B. email
) importieren, wird ein zusätzlicher Nutzer mit demselben Wert generiert.
Das Admin SDK versucht, die gesamte Liste der bereitgestellten Nutzer hochzuladen, auch wenn ein nutzerspezifischer Fehler auftritt. Der Vorgang gibt ein Ergebnis zurück, das die Zusammenfassung erfolgreicher und fehlgeschlagener Importe enthält. Fehlerdetails werden nach einem fehlgeschlagenen Nutzerimport zurückgegeben.
Nutzer mit gehashten HMAC-Passwörtern importieren
Zu den HMAC-Hash-Algorithmen gehören HMAC_MD5
, HMAC_SHA1
, HMAC_SHA256
und HMAC_SHA512
. Sie müssen den Hash-Signer-Schlüssel angeben.
Node.js
getAuth() .importUsers( [ { uid: 'some-uid', email: 'user@example.com', // Must be provided in a byte buffer. passwordHash: Buffer.from('password-hash'), // Must be provided in a byte buffer. passwordSalt: Buffer.from('salt'), }, ], { hash: { algorithm: 'HMAC_SHA256', // Must be provided in a byte buffer. key: Buffer.from('secret'), }, } ) .then((results) => { results.errors.forEach((indexedError) => { console.log(`Error importing user ${indexedError.index}`); }); }) .catch((error) => { console.log('Error importing users :', error); });
Java
try { List<ImportUserRecord> users = Collections.singletonList(ImportUserRecord.builder() .setUid("some-uid") .setEmail("user@example.com") .setPasswordHash("password-hash".getBytes()) .setPasswordSalt("salt".getBytes()) .build()); UserImportOptions options = UserImportOptions.withHash( HmacSha256.builder() .setKey("secret".getBytes()) .build()); UserImportResult result = FirebaseAuth.getInstance().importUsers(users, options); for (ErrorInfo indexedError : result.getErrors()) { System.out.println("Failed to import user: " + indexedError.getReason()); } } catch (FirebaseAuthException e) { System.out.println("Error importing users: " + e.getMessage()); }
Python
users = [ auth.ImportUserRecord( uid='some-uid', email='user@example.com', password_hash=b'password_hash', password_salt=b'salt' ), ] hash_alg = auth.UserImportHash.hmac_sha256(key=b'secret') try: result = auth.import_users(users, hash_alg=hash_alg) for err in result.errors: print('Failed to import user:', err.reason) except exceptions.FirebaseError as error: print('Error importing users:', error)
Go
users := []*auth.UserToImport{ (&auth.UserToImport{}). UID("some-uid"). Email("user@example.com"). PasswordHash([]byte("password-hash")). PasswordSalt([]byte("salt")), } h := hash.HMACSHA256{ Key: []byte("secret"), } result, err := client.ImportUsers(ctx, users, auth.WithHash(h)) if err != nil { log.Fatalln("Error importing users", err) } for _, e := range result.Errors { log.Println("Failed to import user", e.Reason) }
Nutzern mit MD5-, SHA- und TBKDF-gehashten Passwörtern importieren
Die Hash-Algorithmen MD5, SHA und PBKDF sind MD5
, SHA1
, SHA256
, SHA512
, PBKDF_SHA1
und PBKDF2_SHA256
. Sie müssen die Runden angeben, die verwendet werden, um das Passwort zu hashen (zwischen 0 und 8.192 für MD5
, zwischen 1 und 8192 für SHA1
, SHA256
und SHA512
und 0 bis 120.000 für PBKDF_SHA1
und PBKDF2_SHA256
).
Node.js
getAuth() .importUsers( [ { uid: 'some-uid', email: 'user@example.com', // Must be provided in a byte buffer. passwordHash: Buffer.from('password-hash'), // Must be provided in a byte buffer. passwordSalt: Buffer.from('salt'), }, ], { hash: { algorithm: 'PBKDF2_SHA256', rounds: 100000, }, } ) .then((results) => { results.errors.forEach((indexedError) => { console.log(`Error importing user ${indexedError.index}`); }); }) .catch((error) => { console.log('Error importing users :', error); });
Java
try { List<ImportUserRecord> users = Collections.singletonList(ImportUserRecord.builder() .setUid("some-uid") .setEmail("user@example.com") .setPasswordHash("password-hash".getBytes()) .setPasswordSalt("salt".getBytes()) .build()); UserImportOptions options = UserImportOptions.withHash( Pbkdf2Sha256.builder() .setRounds(100000) .build()); UserImportResult result = FirebaseAuth.getInstance().importUsers(users, options); for (ErrorInfo indexedError : result.getErrors()) { System.out.println("Failed to import user: " + indexedError.getReason()); } } catch (FirebaseAuthException e) { System.out.println("Error importing users: " + e.getMessage()); }
Python
users = [ auth.ImportUserRecord( uid='some-uid', email='user@example.com', password_hash=b'password_hash', password_salt=b'salt' ), ] hash_alg = auth.UserImportHash.pbkdf2_sha256(rounds=100000) try: result = auth.import_users(users, hash_alg=hash_alg) for err in result.errors: print('Failed to import user:', err.reason) except exceptions.FirebaseError as error: print('Error importing users:', error)
Go
users := []*auth.UserToImport{ (&auth.UserToImport{}). UID("some-uid"). Email("user@example.com"). PasswordHash([]byte("password-hash")). PasswordSalt([]byte("salt")), } h := hash.PBKDF2SHA256{ Rounds: 100000, } result, err := client.ImportUsers(ctx, users, auth.WithHash(h)) if err != nil { log.Fatalln("Error importing users", err) } for _, e := range result.Errors { log.Println("Failed to import user", e.Reason) }
Nutzer mit standardmäßigen SCRYPT-gehashten Passwörtern importieren
Das Admin SDK unterstützt den Standardalgorithmus SCRYPT
sowie eine interne geänderte Version. Folgende Parameter sind erforderlich:
memoryCost
: Die CPU-/Speicherkosten des Hash-Algorithmus.parallelization
: Die Parallelisierung des Hash-Algorithmus.blockSize
: Die Blockgröße (in der Regel 8) des Hash-Algorithmus.derivedKeyLength
: Die abgeleitete Schlüssellänge des Hash-Algorithmus.
Node.js
getAuth() .importUsers( [ { uid: 'some-uid', email: 'user@example.com', // Must be provided in a byte buffer. passwordHash: Buffer.from('password-hash'), // Must be provided in a byte buffer. passwordSalt: Buffer.from('salt'), }, ], { hash: { algorithm: 'STANDARD_SCRYPT', memoryCost: 1024, parallelization: 16, blockSize: 8, derivedKeyLength: 64, }, } ) .then((results) => { results.errors.forEach((indexedError) => { console.log(`Error importing user ${indexedError.index}`); }); }) .catch((error) => { console.log('Error importing users :', error); });
Java
try { List<ImportUserRecord> users = Collections.singletonList(ImportUserRecord.builder() .setUid("some-uid") .setEmail("user@example.com") .setPasswordHash("password-hash".getBytes()) .setPasswordSalt("salt".getBytes()) .build()); UserImportOptions options = UserImportOptions.withHash( StandardScrypt.builder() .setMemoryCost(1024) .setParallelization(16) .setBlockSize(8) .setDerivedKeyLength(64) .build()); UserImportResult result = FirebaseAuth.getInstance().importUsers(users, options); for (ErrorInfo indexedError : result.getErrors()) { System.out.println("Failed to import user: " + indexedError.getReason()); } } catch (FirebaseAuthException e) { System.out.println("Error importing users: " + e.getMessage()); }
Python
users = [ auth.ImportUserRecord( uid='some-uid', email='user@example.com', password_hash=b'password_hash', password_salt=b'salt' ), ] hash_alg = auth.UserImportHash.standard_scrypt( memory_cost=1024, parallelization=16, block_size=8, derived_key_length=64) try: result = auth.import_users(users, hash_alg=hash_alg) for err in result.errors: print('Failed to import user:', err.reason) except exceptions.FirebaseError as error: print('Error importing users:', error)
Go
users := []*auth.UserToImport{ (&auth.UserToImport{}). UID("some-uid"). Email("user@example.com"). PasswordHash([]byte("password-hash")). PasswordSalt([]byte("salt")), } h := hash.StandardScrypt{ MemoryCost: 1024, Parallelization: 16, BlockSize: 8, DerivedKeyLength: 64, } result, err := client.ImportUsers(ctx, users, auth.WithHash(h)) if err != nil { log.Fatalln("Error importing users", err) } for _, e := range result.Errors { log.Println("Failed to import user", e.Reason) }
Nutzer mit SCRYPT-gehashten Passwörtern in Identity Platform importieren
Identity Platform und Firebase verwenden eine geänderte Version des Algorithmus SCRYPT
. Wenn Sie Nutzer von Firebase zur Identity Platform oder von einem Identity Platform-Projekt zu einem anderen migrieren müssen, benötigen Sie die internen Hash-Parameter.
So greifen Sie auf die Parameter in Identity Platform zu:
- Öffnen Sie in der Google Cloud Console die Seite Nutzer.
- Klicken Sie auf Nutzer importieren. Die Parameter für den Passwort-Hash werden angezeigt.
So greifen Sie auf die Parameter in Firebase zu:
Öffnen Sie den Tab Nutzer in der Firebase Console.
Wählen Sie rechts oben in der Liste der Nutzer aus dem Drop-down-Menü Password-Hash-Parameter aus. Die Parameter für den Passwort-Hash werden angezeigt.
Geben Sie in Ihrem Code Folgendes an:
key
: Der Signierschlüssel, der normalerweise in derbase64
-Codierung angegeben wird.saltSeparator
: (Optional) Das normalerweise in derbase64
-Codierung bereitgestellte Salt-Trennzeichen.rounds
: Die Anzahl der Runden, die zur Verschlüsselung der Passwörter verwendet werden.memoryCost
: die für diesen Algorithmus erforderlichen Arbeitsspeicherkosten
Node.js
getAuth() .importUsers( [ { uid: 'some-uid', email: 'user@example.com', // Must be provided in a byte buffer. passwordHash: Buffer.from('base64-password-hash', 'base64'), // Must be provided in a byte buffer. passwordSalt: Buffer.from('base64-salt', 'base64'), }, ], { hash: { algorithm: 'SCRYPT', // All the parameters below can be obtained from the Firebase Console's users section. // Must be provided in a byte buffer. key: Buffer.from('base64-secret', 'base64'), saltSeparator: Buffer.from('base64SaltSeparator', 'base64'), rounds: 8, memoryCost: 14, }, } ) .then((results) => { results.errors.forEach((indexedError) => { console.log(`Error importing user ${indexedError.index}`); }); }) .catch((error) => { console.log('Error importing users :', error); });
Java
try { List<ImportUserRecord> users = Collections.singletonList(ImportUserRecord.builder() .setUid("some-uid") .setEmail("user@example.com") .setPasswordHash(BaseEncoding.base64().decode("password-hash")) .setPasswordSalt(BaseEncoding.base64().decode("salt")) .build()); UserImportOptions options = UserImportOptions.withHash( Scrypt.builder() // All the parameters below can be obtained from the Firebase Console's "Users" // section. Base64 encoded parameters must be decoded into raw bytes. .setKey(BaseEncoding.base64().decode("base64-secret")) .setSaltSeparator(BaseEncoding.base64().decode("base64-salt-separator")) .setRounds(8) .setMemoryCost(14) .build()); UserImportResult result = FirebaseAuth.getInstance().importUsers(users, options); for (ErrorInfo indexedError : result.getErrors()) { System.out.println("Failed to import user: " + indexedError.getReason()); } } catch (FirebaseAuthException e) { System.out.println("Error importing users: " + e.getMessage()); }
Python
users = [ auth.ImportUserRecord( uid='some-uid', email='user@example.com', password_hash=base64.urlsafe_b64decode('password_hash'), password_salt=base64.urlsafe_b64decode('salt') ), ] # All the parameters below can be obtained from the Firebase Console's "Users" # section. Base64 encoded parameters must be decoded into raw bytes. hash_alg = auth.UserImportHash.scrypt( key=base64.b64decode('base64_secret'), salt_separator=base64.b64decode('base64_salt_separator'), rounds=8, memory_cost=14 ) try: result = auth.import_users(users, hash_alg=hash_alg) for err in result.errors: print('Failed to import user:', err.reason) except exceptions.FirebaseError as error: print('Error importing users:', error)
Go
b64URLdecode := func(s string) []byte { b, err := base64.URLEncoding.DecodeString(s) if err != nil { log.Fatalln("Failed to decode string", err) } return b } b64Stddecode := func(s string) []byte { b, err := base64.StdEncoding.DecodeString(s) if err != nil { log.Fatalln("Failed to decode string", err) } return b } // Users retrieved from Firebase Auth's backend need to be base64URL decoded users := []*auth.UserToImport{ (&auth.UserToImport{}). UID("some-uid"). Email("user@example.com"). PasswordHash(b64URLdecode("password-hash")). PasswordSalt(b64URLdecode("salt")), } // All the parameters below can be obtained from the Firebase Console's "Users" // section. Base64 encoded parameters must be decoded into raw bytes. h := hash.Scrypt{ Key: b64Stddecode("base64-secret"), SaltSeparator: b64Stddecode("base64-salt-separator"), Rounds: 8, MemoryCost: 14, } result, err := client.ImportUsers(ctx, users, auth.WithHash(h)) if err != nil { log.Fatalln("Error importing users", err) } for _, e := range result.Errors { log.Println("Failed to import user", e.Reason) }
Nutzer mit BCRYMP-gehashtesn Passwörtern importieren
Für BCRYPT
-gehashte Passwörter sind keine zusätzlichen Parameter oder Salts erforderlich.
Node.js
getAuth() .importUsers( [ { uid: 'some-uid', email: 'user@example.com', // Must be provided in a byte buffer. passwordHash: Buffer.from('password-hash'), }, ], { hash: { algorithm: 'BCRYPT', }, } ) .then((results) => { results.errors.forEach((indexedError) => { console.log(`Error importing user ${indexedError.index}`); }); }) .catch((error) => { console.log('Error importing users :', error); });
Java
try { List<ImportUserRecord> users = Collections.singletonList(ImportUserRecord.builder() .setUid("some-uid") .setEmail("user@example.com") .setPasswordHash("password-hash".getBytes()) .setPasswordSalt("salt".getBytes()) .build()); UserImportOptions options = UserImportOptions.withHash(Bcrypt.getInstance()); UserImportResult result = FirebaseAuth.getInstance().importUsers(users, options); for (ErrorInfo indexedError : result.getErrors()) { System.out.println("Failed to import user: " + indexedError.getReason()); } } catch (FirebaseAuthException e) { System.out.println("Error importing users: " + e.getMessage()); }
Python
users = [ auth.ImportUserRecord( uid='some-uid', email='user@example.com', password_hash=b'password_hash', password_salt=b'salt' ), ] hash_alg = auth.UserImportHash.bcrypt() try: result = auth.import_users(users, hash_alg=hash_alg) for err in result.errors: print('Failed to import user:', err.reason) except exceptions.FirebaseError as error: print('Error importing users:', error)
Go
users := []*auth.UserToImport{ (&auth.UserToImport{}). UID("some-uid"). Email("user@example.com"). PasswordHash([]byte("password-hash")). PasswordSalt([]byte("salt")), } h := hash.Bcrypt{} result, err := client.ImportUsers(ctx, users, auth.WithHash(h)) if err != nil { log.Fatalln("Error importing users", err) } for _, e := range result.Errors { log.Println("Failed to import user", e.Reason) }
Nutzer ohne Passwörter importieren
Wenn Ihre Nutzer sich mit einem externen Identitätsanbieter über OAuth, SAML oder OIDC authentifizieren, haben Sie keinen direkten Zugriff auf ihr Passwort.
Node.js
getAuth() .importUsers([ { uid: 'some-uid', displayName: 'John Doe', email: 'johndoe@gmail.com', photoURL: 'http://www.example.com/12345678/photo.png', emailVerified: true, phoneNumber: '+11234567890', // Set this user as admin. customClaims: { admin: true }, // User with Google provider. providerData: [ { uid: 'google-uid', email: 'johndoe@gmail.com', displayName: 'John Doe', photoURL: 'http://www.example.com/12345678/photo.png', providerId: 'google.com', }, ], }, ]) .then((results) => { results.errors.forEach((indexedError) => { console.log(`Error importing user ${indexedError.index}`); }); }) .catch((error) => { console.log('Error importing users :', error); });
Java
try { List<ImportUserRecord> users = Collections.singletonList(ImportUserRecord.builder() .setUid("some-uid") .setDisplayName("John Doe") .setEmail("johndoe@gmail.com") .setPhotoUrl("http://www.example.com/12345678/photo.png") .setEmailVerified(true) .setPhoneNumber("+11234567890") .putCustomClaim("admin", true) // set this user as admin .addUserProvider(UserProvider.builder() // user with Google provider .setUid("google-uid") .setEmail("johndoe@gmail.com") .setDisplayName("John Doe") .setPhotoUrl("http://www.example.com/12345678/photo.png") .setProviderId("google.com") .build()) .build()); UserImportResult result = FirebaseAuth.getInstance().importUsers(users); for (ErrorInfo indexedError : result.getErrors()) { System.out.println("Failed to import user: " + indexedError.getReason()); } } catch (FirebaseAuthException e) { System.out.println("Error importing users: " + e.getMessage()); }
Python
users = [ auth.ImportUserRecord( uid='some-uid', display_name='John Doe', email='johndoe@gmail.com', photo_url='http://www.example.com/12345678/photo.png', email_verified=True, phone_number='+11234567890', custom_claims={'admin': True}, # set this user as admin provider_data=[ # user with Google provider auth.UserProvider( uid='google-uid', email='johndoe@gmail.com', display_name='John Doe', photo_url='http://www.example.com/12345678/photo.png', provider_id='google.com' ) ], ), ] try: result = auth.import_users(users) for err in result.errors: print('Failed to import user:', err.reason) except exceptions.FirebaseError as error: print('Error importing users:', error)
Go
users := []*auth.UserToImport{ (&auth.UserToImport{}). UID("some-uid"). DisplayName("John Doe"). Email("johndoe@gmail.com"). PhotoURL("http://www.example.com/12345678/photo.png"). EmailVerified(true). PhoneNumber("+11234567890"). CustomClaims(map[string]interface{}{"admin": true}). // set this user as admin ProviderData([]*auth.UserProvider{ // user with Google provider { UID: "google-uid", Email: "johndoe@gmail.com", DisplayName: "John Doe", PhotoURL: "http://www.example.com/12345678/photo.png", ProviderID: "google.com", }, }), } result, err := client.ImportUsers(ctx, users) if err != nil { log.Fatalln("Error importing users", err) } for _, e := range result.Errors { log.Println("Failed to import user", e.Reason) }
Beachten Sie, dass providerId
in Identity Platform zur Beschreibung eines bestimmten Anbieters verwendet wird. Bei OIDC- und SAML-Anbietern wird dies während der Erstellung definiert.
Für andere Anbieter hat dies einen vordefinierten Wert (z. B. google.com
oder facebook.com
). Sie können die providerId
aus den Anforderungen des angemeldeten Nutzers abrufen.
Nutzer mit mehreren Authentifizierungsfaktoren importieren
Wenn vorhandene Nutzer Telefonnummern haben, die für die Multi-Faktor-Authentifizierung registriert sind, können Sie sie in Identity Platform importieren.
Multi-Faktor-Nutzer benötigen eine bestätigte E-Mail und einen unterstützten ersten Faktor. Pro Nutzer sind maximal fünf sekundäre Faktoren zulässig.
Sie können die folgenden Multi-Faktor-Attribute importieren:
Attribut | Typ | Beschreibung |
---|---|---|
uid |
String |
Eine optionale eindeutige ID des registrierten zweiten Faktors. Wenn nicht angegeben, wird automatisch ein zufälliger uid generiert.
|
phoneNumber |
String | Telefonnummer für den registrierten zweiten Faktor. Diese Telefonnummer muss E.164-konform sein. |
displayName |
String | Ein Optionaler Anzeigename. Dieser ist nützlich, wenn ein Nutzer mehrere registrierte zweite Faktoren hat. |
enrollmentTime |
String | Das Datum, an dem der zweite Faktor registriert wurde, formatiert als UTC-String. Wenn nicht angegeben, wird das aktuelle Datum verwendet. |
factorId |
String |
Die Typ-ID des zweiten Faktors. Diese ist immer auf phone festgelegt.
|
Das folgende Beispiel zeigt, wie Multi-Faktor-Nutzer importiert werden:
Node.js
// Up to 1000 users can be imported at once.
const userImportRecords = [
{
uid: 'uid1',
email: 'user1@example.com',
emailVerified: true,
passwordHash: Buffer.from('passwordHash1'),
passwordSalt: Buffer.from('salt1'),
multiFactor: {
enrolledFactors: [
{
// Enrolled second factor uid is optional.
uid: 'uid1-unique-mfa-identifier1',
displayName: 'Personal phone',
phoneNumber: '+16505551234',
factorId: 'phone',
// Enrollment time is also optional.
enrollmentTime: 'Fri, 22 Sep 2017 01:49:58 GMT',
},
],
},
},
{
// User with multiple second factors.
uid: 'uid2',
email: 'user2@example.com',
emailVerified: true,
passwordHash: Buffer.from('passwordHash2'),
passwordSalt: Buffer.from('salt2'),
multiFactor: {
enrolledFactors: [
{
displayName: 'Work phone',
phoneNumber: '+16505550007',
factorId: 'phone',
},
{
displayName: 'Backup phone',
phoneNumber: '+16505550008',
factorId: 'phone',
},
],
},
},
{
// User with no second factor.
uid: 'uid3',
email: 'user3@example.com',
passwordHash: Buffer.from('passwordHash3'),
passwordSalt: Buffer.from('salt3'),
},
...
];
const userImportOptions = {
hash: {
algorithm: 'HMAC_SHA256',
key: Buffer.from('secretKey'),
},
};
admin.auth().importUsers(userImportRecords, userImportOptions)
.then((userImportResult) => {
// The number of successful imports is determined via: userImportResult.successCount.
// The number of failed imports is determined via: userImportResult.failureCount.
// To get the error details.
userImportResult.forEach(function(indexedError) {
// The corresponding user that failed to upload.
console.log(userImportRecords[indexedError.index].uid +' failed to import',
indexedError.error);
});
})
.catch((error) => {
// Some unrecoverable error occurred that prevented the operation from running.
});
Mit der Befehlszeile
Wenn die Nutzerdaten als JSON oder CSV gespeichert sind, können Sie sie mit dem Firebase-Befehlszeilentool importieren:
firebase auth:import account_file \
--hash-algo=[HASH-ALGORITHM] \
--hash-key=[KEY] \
--salt-separator=[SALT-SEPARATOR] \
--rounds=[ROUNDS] \
--mem-cost=[MEM-COST] \
--parallelization=[PARALLELIZATION] \
--block-size=[BLOCK-SIZE] \
--dk-len=[DK-LEN] \
--hash-input-order=[HASH-INPUT-ORDER] \
Eine vollständige Beschreibung der einzelnen Parameter finden Sie in der Referenzdokumentation zur Befehlszeile.
Nächste Schritte
- Häufige Fehlercodes beim Importieren von Nutzern
- Authentifizierung von Nutzern in App Engine mithilfe von Identity Platform
- Benutzerdefinierte Ansprüche mit Identity Platform konfigurieren
- Informationen zur Admin Auth API