Mengelola tenant Identity Platform secara terprogram

Dokumen ini menjelaskan cara menggunakan Identity Platform Admin SDK untuk mengelola tenant dan penggunanya secara terprogram. Beberapa aktivitas yang dapat Anda lakukan sebagai administrator antara lain:

  • Pengelolaan pengguna: Membuat, memperbarui, menghapus, dan mencantumkan pengguna untuk tenant tertentu.

  • Verifikasi identitas: Identifikasi pengguna aplikasi untuk membatasi akses ke resource di server Anda sendiri.

  • Impor pengguna: Migrasikan pengguna dari sistem autentikasi eksternal atau project atau tenant Identity Platform lainnya.

  • Kontrol akses dengan klaim kustom: Menentukan atribut khusus pada akun pengguna untuk tenant tertentu dan menerapkan berbagai strategi kontrol akses, seperti kontrol akses berbasis peran.

  • Pengelolaan sesi pengguna: Mencabut token refresh pengguna untuk tenant tertentu.

  • Link tindakan email: Membuat link email yang disesuaikan untuk reset sandi, login dengan link email, dan verifikasi email bagi pengguna tenant tertentu.

  • Pengelolaan tenant: Membuat, mencantumkan, mendapatkan, memperbarui, menghapus tenant untuk project Identity Platform tertentu.

  • Mengelola penyedia OIDC dan SAML di tenant: Mengelola konfigurasi OIDC dan SAML secara terprogram pada tenant yang ditentukan.

Sebelum memulai

Fitur yang didukung

Tabel berikut mencantumkan fitur yang didukung oleh setiap SDK di lingkungan multi-tenant:

Fitur Node.js Java Python Go C#
Pembuatan token kustom
Memverifikasi token ID
Mengelola pengguna
Mengontrol akses dengan klaim kustom
Mencabut token refresh
Mengimpor pengguna
Membuat link tindakan email
Autentikasi multi-faktor
Mengelola konfigurasi penyedia SAML/OIDC
Pengelolaan cookie sesi

Tabel berikut menunjukkan metode login yang dapat Anda konfigurasi menggunakan Admin SDK dan Konsol Google Cloud dalam konteks khusus tenant:

Fitur Konsol Google Cloud Admin SDK
Email
OIDC
SAML
Sosial
Telepon
Autentikasi multi-faktor
Anonim

Manajemen penyewa

Dengan Admin SDK, Anda dapat mengelola tenant secara terprogram dari lingkungan server yang aman, bukan menggunakan Konsol Google Cloud. Hal ini mencakup kemampuan untuk membuat, mencantumkan, mendapatkan, mengubah, atau menghapus tenant.

Setiap tenant berisi penyedia identitas, setelan, dan kumpulan penggunanya sendiri. Operasi manajemen konfigurasi tenant (CRUD) tersedia dari instance project induk menggunakan admin.auth().tenantManager().

Konfigurasi tenant memberikan informasi tentang tenant, seperti nama tampilan, ID tenant, dan konfigurasi autentikasi emailnya.

Semua setelan lainnya (seperti domain yang diizinkan dan URI pengalihan yang diautentikasi) tenant akan diwariskan dari project induk. Layanan ini harus dikelola menggunakan Konsol Google Cloud.

Untuk operasi seperti pengelolaan pengguna khusus tenant, mengonfigurasi penyedia OIDC/SAML, dan pembuatan link email, Anda memerlukan instance TenantAwareAuth untuk tenant target (yang diidentifikasi oleh tenantId uniknya).

Node.js

const tenantManager = admin.auth().tenantManager();
const tenantAuth = tenantManager.authForTenant(tenantId);

Python

from firebase_admin import tenant_mgt

tenant_client = tenant_mgt.auth_for_tenant(tenant_id)

Java

FirebaseAuth auth = FirebaseAuth.getInstance();
TenantManager tenantManager = auth.getTenantManager();
TenantAwareFirebaseAuth tenantAuth = tenantManager.getAuthForTenant(tenantId);

Semua panggilan ke API pengelolaan pengguna, API pengelolaan penyedia OIDC/SAML, dan API pembuatan link email akan berada dalam cakupan tenant ini (menggunakan instance TenantAwareAuth).

Mendapatkan tenant yang ada

Admin SDK menyediakan metode getTenant(), yang mengambil informasi tentang tenant berdasarkan tenantId-nya (ID unik untuk tenant).

Node.js

admin.auth().tenantManager().getTenant(tenantId)
  .then((tenant) => {
    console.log(tenant.toJSON());
  })
  .catch((error) => {
    // Handle error.
  });

Python

tenant = tenant_mgt.get_tenant(tenant_id)

print('Retreieved tenant:', tenant.tenant_id)

Java

Tenant tenant = FirebaseAuth.getInstance().getTenantManager().getTenant(tenantId);
System.out.println("Retrieved tenant: " + tenant.getTenantId());

Metode ini menampilkan objek Tenant yang sesuai dengan tenantId. Jika tenantId yang diberikan bukan milik tenant yang ada, promise yang ditampilkan akan ditolak dengan error auth/tenant-not-found.

Berhati-hatilah agar tidak tertukar antara instance Tenant dengan objek TenantAwareAuth. authInstance.tenantManager().authForTenant() menampilkan instance TenantAwareAuth yang memperluas BaseAuth. Class Auth juga memperluas BaseAuth. BaseAuth menyediakan API untuk mengelola pengguna, mengonfigurasi penyedia OIDC/SAML dalam berbagai konteks. Untuk Auth, konteksnya berada di level project induk. Untuk TenantAwareAuth, konteksnya berada di level tenant (tenant ditentukan oleh ID tenant). Metode getTenant() akan di-resolve dengan informasi tenant dasar (seperti ID tenant, nama tampilan, dan setelan penyedia email), tetapi untuk memanggil API di tenant tersebut, Anda perlu menggunakan authForTenant(tenantFromGetTenant.tenantId).

Membuat tenant

Gunakan metode createTenant() untuk membuat konfigurasi tenant baru:

Node.js

admin.auth().tenantManager().createTenant({
  displayName: 'myTenant1',
  emailSignInConfig: {
    enabled: true,
    passwordRequired: false, // Email link sign-in enabled.
  },
  // TODO: Remove if you don't want to enable multi-factor authentication.
  multiFactorConfig: {
    state: 'ENABLED',
    factorIds: ['phone']
  },
  // TODO: Remove if you don't want to register test phone numbers for use
  // with multi-factor authentication.
  testPhoneNumbers: {
    '+16505551234': '145678',
    '+16505550000': '123456'
  },
})
.then((createdTenant) => {
  console.log(createdTenant.toJSON());
})
.catch((error) => {
  // Handle error.
});

Python

tenant = tenant_mgt.create_tenant(
    display_name='myTenant1',
    enable_email_link_sign_in=True,
    allow_password_sign_up=True)

print('Created tenant:', tenant.tenant_id)

Java

Tenant.CreateRequest request = new Tenant.CreateRequest()
    .setDisplayName("myTenant1")
    .setEmailLinkSignInEnabled(true)
    .setPasswordSignInAllowed(true);
Tenant tenant = FirebaseAuth.getInstance().getTenantManager().createTenant(request);
System.out.println("Created tenant: " + tenant.getTenantId());

Anda dapat memberikan kombinasi properti ini:

Properti Jenis Deskripsi
displayName

string
    
Nama tampilan tenant. Kolom ini harus terdiri dari 4-20 karakter, yang terdiri dari huruf, angka, dan tanda hubung, serta harus diawali dengan huruf.
emailSignInConfig

{
  enable: boolean,
  passwordRequired: boolean
}
    
Konfigurasi penyedia login email. Hal ini termasuk apakah penyedia email diaktifkan atau tidak, dan apakah sandi diperlukan untuk login dengan email. Jika tidak diwajibkan, login dengan email dapat dilakukan dengan sandi atau menggunakan metode login dengan link email.
multiFactorConfig

{
  state: 'DISABLED' | 'ENABLED',
  factorIds: string[]
}
    
Apakah autentikasi multi-faktor diaktifkan untuk tenant, dan jenis faktor yang diizinkan. Saat ini, satu-satunya ID faktor yang didukung adalah phone.
testPhoneNumbers

{
  string: string
}
  
Peta nomor telepon dan kode autentikasi multi-faktor yang terkait untuk didaftarkan untuk tujuan pengujian. Anda hanya boleh mengirimkan maksimum 10 entri. Untuk menghapus semua nomor telepon pengujian, tetapkan kolom ini ke null.

Metode ini menampilkan objek Tenant untuk tenant yang baru dibuat.

Memperbarui tenant

Gunakan metode updateTenant() untuk mengubah data tenant yang ada. Anda harus menentukan tenantId, beserta properti yang akan diperbarui untuk tenant tersebut.

Node.js

admin.auth().tenantManager().updateTenant(tenantId, {
  displayName: 'updatedName',
  emailSignInConfig: {
    enabled: false, // Disable email provider.
  },
  // Enable multi-factor authentication.
  multiFactorConfig: {
    state: 'ENABLED',
    factorIds: ['phone']
  },
  // Register phone numbers for testing.
  testPhoneNumbers: {
    '+16505551234': '145678',
    '+16505550000': '123456'
  },
})
.then((updatedTenant) => {
  console.log(updatedTenant.toJSON());
})
.catch((error) => {
  // Handle error.
});

Python

tenant = tenant_mgt.update_tenant(
    tenant_id,
    display_name='updatedName',
    allow_password_sign_up=False) # Disable email provider

print('Updated tenant:', tenant.tenant_id)

Java

Tenant.UpdateRequest request = new Tenant.UpdateRequest(tenantId)
    .setDisplayName("updatedName")
    .setPasswordSignInAllowed(false);
Tenant tenant = FirebaseAuth.getInstance().getTenantManager().updateTenant(request);
System.out.println("Updated tenant: " + tenant.getTenantId());

updateTenant() menerima properti yang sama seperti createTenant(). Semua properti bersifat opsional. Jika properti tidak ditentukan, nilai yang ada tidak akan diubah.

Metode ini akan menampilkan objek Tenant yang diperbarui setelah selesai. Jika tenantId yang disediakan bukan milik tenant yang ada, promise yang ditampilkan akan ditolak dengan error auth/tenant-not-found.

Menghapus tenant

Anda dapat menghapus tenant menggunakan tenantId-nya:

Node.js

admin.auth().tenantManager().deleteTenant(tenantId)
  .then(() => {
    // Tenant deleted.
  })
  .catch((error) => {
    // Handle error.
  });

Python

tenant_mgt.delete_tenant(tenant_id)

Java

FirebaseAuth.getInstance().getTenantManager().deleteTenant(tenantId);

Metode ini akan menampilkan hasil kosong saat penghapusan berhasil diselesaikan. Jika tenantId yang diberikan bukan milik tenant yang ada, promise yang ditampilkan akan ditolak dengan error auth/tenant-not-found.

Mencantumkan tenant

Gunakan metode listTenants() untuk menampilkan tenant yang ada:

Node.js

function listAllTenants(nextPageToken) {
  return admin.auth().tenantManager().listTenants(100, nextPageToken)
    .then((result) => {
      result.tenants.forEach((tenant) => {
        console.log(tenant.toJSON());
      });
      if (result.pageToken) {
        return listAllTenants(result.pageToken);
      }
    });
}

listAllTenants();

Python

for tenant in tenant_mgt.list_tenants().iterate_all():
    print('Retrieved tenant:', tenant.tenant_id)

Java

ListTenantsPage page = FirebaseAuth.getInstance().getTenantManager().listTenants(null);
for (Tenant tenant : page.iterateAll()) {
  System.out.println("Retrieved tenant: " + tenant.getTenantId());
}

Setiap batch hasil berisi daftar tenant, ditambah token halaman berikutnya untuk menampilkan daftar batch tenant berikutnya. Setelah semua tenant sudah tercantum, tidak ada pageToken yang ditampilkan.

Jika tidak ada kolom maxResults yang ditentukan, defaultnya adalah 1.000 tenant per batch. Ini juga merupakan jumlah maksimum tenant yang diizinkan untuk dicantumkan dalam satu waktu. Nilai apa pun yang lebih besar dari nilai maksimum akan menampilkan error argumen. Jika pageToken tidak ditentukan, metode ini akan mencantumkan tenant dari awal.

Mengelola penyedia SAML dan OIDC secara terprogram

Admin SDK menyediakan API untuk mengelola konfigurasi penyedia Security Assertion Markup Language (SAML) 2.0 dan OpenID Connect (OIDC) secara terprogram dari lingkungan server yang aman.

Dengan Admin SDK, Anda dapat mengelola penyedia ini untuk tenant tertentu. Hal ini mirip dengan mengelola penyedia OIDC dan SAML tingkat project.

Untuk mengelola penyedia untuk tenant, buat instance TenantAwareAuth terlebih dahulu:

Node.js

const tenantAuth = admin.auth().tenantManager().authForTenant('TENANT-ID');

Python

tenant_client = tenant_mgt.auth_for_tenant('TENANT-ID')

Java

TenantAwareFirebaseAuth tenantAuth = FirebaseAuth.getInstance().getTenantManager()
    .getAuthForTenant("TENANT-ID");

Kemudian, Anda dapat melakukan operasi umum, seperti membuat, mengubah, atau menghapus penyedia untuk tenant.

Membuat penyedia

Kode berikut menunjukkan cara membuat penyedia SAML untuk tenant:

Node.js

const newConfig = {
  displayName: 'SAML provider name',
  enabled: true,
  providerId: 'saml.myProvider',
  idpEntityId: 'IDP_ENTITY_ID',
  ssoURL: 'https://example.com/saml/sso/1234/',
  x509Certificates: [
    '-----BEGIN CERTIFICATE-----\nCERT1...\n-----END CERTIFICATE-----',
    '-----BEGIN CERTIFICATE-----\nCERT2...\n-----END CERTIFICATE-----'
  ],
  rpEntityId: 'RP_ENTITY_ID',
  // Using the default callback URL.
  callbackURL: 'https://project-id.firebaseapp.com/__/auth/handler'
};

tenantAuth.createProviderConfig(newConfig).then(() => {
  // Successful creation.
}).catch((error) => {
  // Handle error.
});

Python

saml = tenant_client.create_saml_provider_config(
    display_name='SAML provider name',
    enabled=True,
    provider_id='saml.myProvider',
    idp_entity_id='IDP_ENTITY_ID',
    sso_url='https://example.com/saml/sso/1234/',
    x509_certificates=[
        '-----BEGIN CERTIFICATE-----\nCERT1...\n-----END CERTIFICATE-----',
        '-----BEGIN CERTIFICATE-----\nCERT2...\n-----END CERTIFICATE-----',
    ],
    rp_entity_id='P_ENTITY_ID',
    callback_url='https://project-id.firebaseapp.com/__/auth/handler')

print('Created new SAML provider:', saml.provider_id)

Java

SamlProviderConfig.CreateRequest request = new SamlProviderConfig.CreateRequest()
    .setDisplayName("SAML provider name")
    .setEnabled(true)
    .setProviderId("saml.myProvider")
    .setIdpEntityId("IDP_ENTITY_ID")
    .setSsoUrl("https://example.com/saml/sso/1234/")
    .addX509Certificate("-----BEGIN CERTIFICATE-----\nCERT1...\n-----END CERTIFICATE-----")
    .addX509Certificate("-----BEGIN CERTIFICATE-----\nCERT2...\n-----END CERTIFICATE-----")
    .setRpEntityId("RP_ENTITY_ID")
    .setCallbackUrl("https://project-id.firebaseapp.com/__/auth/handler");
SamlProviderConfig saml = tenantAuth.createSamlProviderConfig(request);
System.out.println("Created new SAML provider: " + saml.getProviderId());

Mengubah penyedia

Kode berikut menunjukkan cara mengubah penyedia:

Node.js

const updatedConfig = {
  x509Certificates: [
    '-----BEGIN CERTIFICATE-----\nCERT2...\n-----END CERTIFICATE-----',
    '-----BEGIN CERTIFICATE-----\nCERT3...\n-----END CERTIFICATE-----',
  ],
};
tenantAuth.updateProviderConfig('saml.myProvider', updatedConfig).then(() => {
  // Successful update.
}).catch((error) => {
  // Handle error.
});

Python

saml = tenant_client.update_saml_provider_config(
    'saml.myProvider',
    x509_certificates=[
        '-----BEGIN CERTIFICATE-----\nCERT2...\n-----END CERTIFICATE-----',
        '-----BEGIN CERTIFICATE-----\nCERT3...\n-----END CERTIFICATE-----',
    ])

print('Updated SAML provider:', saml.provider_id)

Java

SamlProviderConfig.UpdateRequest request =
    new SamlProviderConfig.UpdateRequest("saml.myProvider")
      .addX509Certificate("-----BEGIN CERTIFICATE-----\nCERT2...\n-----END CERTIFICATE-----")
      .addX509Certificate("-----BEGIN CERTIFICATE-----\nCERT3...\n-----END CERTIFICATE-----");
SamlProviderConfig saml = tenantAuth.updateSamlProviderConfig(request);
System.out.println("Updated SAML provider: " + saml.getProviderId());

Mendapatkan penyedia

Kode berikut menunjukkan cara mengambil konfigurasi penyedia untuk tenant tertentu menggunakan ID penyedianya:

Node.js

tenantAuth.getProviderConfig('saml.myProvider').then((config) => {
  // Get display name and whether it is enabled.
  console.log(config.displayName, config.enabled);
}).catch((error) => {
  // Handle error. Common error is that config is not found.
});

Python

saml = tennat_client.get_saml_provider_config('saml.myProvider')
print(saml.display_name, saml.enabled)

Java

SamlProviderConfig saml = tenantAuth.getSamlProviderConfig("saml.myProvider");

// Get display name and whether it is enabled.
System.out.println(saml.getDisplayName() + " " + saml.isEnabled());

Penyedia listingan

Kode berikut menunjukkan cara menampilkan daftar konfigurasi penyedia untuk tenant tertentu:

Node.js

// Returns 10 SAML provider configs starting from the specified nextPageToken offset.
tenantAuth.listProviderConfigs({type: 'saml', maxResults: 10, pageToken: 'nextPageToken'}).then((results) => {
  results.providerConfigs.forEach((config) => {
    console.log(config.providerId);
  });
  // To list the next 10:
  // return tenantAuth.listProviderConfigs(
  //     {type: 'saml', maxResults: 10, pageToken: results.pageToken});
}).catch((error) => {
  // Handle error.
});

Python

for saml in tenant_client.list_saml_provider_configs('nextPageToken').iterate_all():
    print(saml.provider_id)

Java

ListProviderConfigsPage<SamlProviderConfig> page = tenantAuth.listSamlProviderConfigs(
    "nextPageToken");
for (SamlProviderConfig saml : page.iterateAll()) {
  System.out.println(saml.getProviderId());
}

Menghapus penyedia

Kode berikut menunjukkan cara menghapus penyedia:

Node.js

tenantAuth.deleteProviderConfig('saml.myProvider').then(() => {
  // Successful deletion.
}).catch((error) => {
  // Handle error.
});

Python

tenant_client.delete_saml_provider_config('saml.myProvider')

Java

tenantAuth.deleteSamlProviderConfig("saml.myProvider");

Penyedia OIDC dikelola seperti penyedia OIDC level project, kecuali penyedia OIDC dapat dikelola dari instance TenantAwareAuth yang terkait, bukan instance level project Auth.

Untuk mempelajari lebih lanjut, lihat Mengelola penyedia SAML dan OIDC secara terprogram.

Mengelola pengguna khusus tenant

Anda dapat menggunakan Admin SDK untuk membuat, mengambil, memperbarui, menghapus, dan menampilkan daftar semua pengguna untuk tenant tertentu.

Untuk memulai, Anda memerlukan instance TenantAwareAuth untuk tenant yang sesuai:

Node.js

const tenantAuth = admin.auth().tenantManager().authForTenant('TENANT-ID');

Python

tenant_client = tenant_mgt.auth_for_tenant('TENANT-ID')

Java

TenantAwareFirebaseAuth tenantAuth = FirebaseAuth.getInstance().getTenantManager()
    .getAuthForTenant("TENANT-ID");

Mendapatkan pengguna

Anda dapat mengambil pengguna khusus tenant dengan ID uid:

Node.js

tenantAuth.getUser(uid)
  .then((userRecord) => {
    // See the UserRecord reference documentation to learn more.
    console.log('Successfully fetched user data:', userRecord.toJSON());
    // Tenant ID will be reflected in userRecord.tenantId.
  })
  .catch((error) => {
    console.log('Error fetching user data:', error);
  });

Python

	# Get an auth.Client from tenant_mgt.auth_for_tenant()
    user = tenant_client.get_user(uid)
    print('Successfully fetched user data:', user.uid)

Java

// Get an auth client from the firebase.App
UserRecord user = tenantAuth.getUser(uid);
System.out.println("Successfully fetched user data: " + user.getDisplayName());

Anda juga dapat mengidentifikasi pengguna melalui emailnya:

Node.js

tenantAuth.getUserByEmail(email)
  .then((userRecord) => {
    // See the UserRecord reference documentation to learn more.
    console.log('Successfully fetched user data:', userRecord.toJSON());
    // Tenant ID will be reflected in userRecord.tenantId.
  })
  .catch((error) => {
    console.log('Error fetching user data:', error);
  });

Python

user = tenant_client.get_user_by_email(email)
print('Successfully fetched user data:', user.uid)

Java

// Get an auth client from the firebase.App
UserRecord user = tenantAuth.getUserByEmail(email);
System.out.println("Successfully fetched user data: " + user.getDisplayName());

Membuat pengguna

Gunakan metode createUser() untuk membuat pengguna baru untuk tenant tertentu. Saat membuat pengguna baru, pemberian uid bersifat opsional. Jika tidak ditentukan, Identity Platform akan menyediakan pengguna yang unik.

Node.js

tenantAuth.createUser({
  email: 'user@example.com',
  emailVerified: false,
  phoneNumber: '+11234567890',
  password: 'secretPassword',
  displayName: 'John Doe',
  photoURL: 'http://www.example.com/12345678/photo.png',
  disabled: false
})
.then((userRecord) => {
  // See the UserRecord reference documentation to learn more.
  console.log('Successfully created new user:', userRecord.uid);
  // Tenant ID will be reflected in userRecord.tenantId.
})
.catch((error) => {
  console.log('Error creating new user:', error);
});

Python

user = tenant_client.create_user(
    email='user@example.com',
    email_verified=False,
    phone_number='+15555550100',
    password='secretPassword',
    display_name='John Doe',
    photo_url='http://www.example.com/12345678/photo.png',
    disabled=False)
print('Sucessfully created new user:', user.uid)

Java

UserRecord.CreateRequest request = new UserRecord.CreateRequest()
    .setEmail("user@example.com")
    .setEmailVerified(false)
    .setPhoneNumber("+15555550100")
    .setPassword("secretPassword")
    .setDisplayName("John Doe")
    .setPhotoUrl("http://www.example.com/12345678/photo.png")
    .setDisabled(false);
UserRecord user = tenantAuth.createUser(request);
System.out.println("Successfully created user: " + user.getDisplayName());

Mengubah pengguna

Anda dapat memodifikasi pengguna yang ada dengan menentukan uid mereka ke metode updateUser():

Node.js

tenantAuth.updateUser(uid, {
  email: 'modifiedUser@example.com',
  phoneNumber: '+11234567890',
  emailVerified: true,
  password: 'newPassword',
  displayName: 'Jane Doe',
  photoURL: 'http://www.example.com/12345678/photo.png',
  disabled: true
})
.then((userRecord) => {
  // See the UserRecord reference documentation to learn more.
  console.log('Successfully updated user', userRecord.toJSON());
})
.catch((error) => {
  console.log('Error updating user:', error);
});

Python

user = tenant_client.update_user(
    uid,
    email='user@example.com',
    phone_number='+15555550100',
    email_verified=True,
    password='newPassword',
    display_name='John Doe',
    photo_url='http://www.example.com/12345678/photo.png',
    disabled=True)
print('Sucessfully updated user:', user.uid)

Java

UserRecord.UpdateRequest request = new UserRecord.UpdateRequest(uid)
    .setEmail("user@example.com")
    .setEmailVerified(true)
    .setPhoneNumber("+15555550100")
    .setPassword("newPassword")
    .setDisplayName("John Doe")
    .setPhotoUrl("http://www.example.com/12345678/photo.png")
    .setDisabled(true);
UserRecord user = tenantAuth.updateUser(request);
System.out.println("Successfully updated user: " + user.getDisplayName());

Menghapus pengguna

Contoh berikut menunjukkan cara menghapus pengguna berdasarkan uid mereka:

Node.js

tenantAuth.deleteUser(uid)
  .then(() => {
    console.log('Successfully deleted user');
  })
  .catch((error) => {
    console.log('Error deleting user:', error);
  });

Python

tenant_client.delete_user(uid)
print('Successfully deleted user')

Java

tenantAuth.deleteUser(uid);

System.out.println("Successfully deleted user: " + uid);

Menampilkan daftar pengguna

Untuk mengambil seluruh daftar pengguna untuk tenant tertentu dalam batch, gunakan metode listUsers(). Setiap batch akan berisi daftar data pengguna, ditambah token halaman berikutnya jika ada pengguna tambahan.

Node.js

function listAllUsers(nextPageToken) {
  // List batch of users, 1000 at a time.
  tenantAuth.listUsers(1000, nextPageToken)
    .then((listUsersResult) => {
      listUsersResult.users.forEach((userRecord) => {
        console.log('user', userRecord.toJSON());
        // Tenant ID will be reflected in userRecord.tenantId.
      });
      if (listUsersResult.pageToken) {
        // List next batch of users.
        listAllUsers(listUsersResult.pageToken);
      }
    })
    .catch((error) => {
      console.log('Error listing users:', error);
    });
}
// Start listing users from the beginning, 1000 at a time.
listAllUsers();

Python

	# Note, behind the scenes, the iterator will retrive 1000 users at a time through the API
    for user in tenant_client.list_users().iterate_all():
        print('User: ' + user.uid)

	# Iterating by pages of 1000 users at a time.
    page = tenant_client.list_users()
    while page:
        for user in page.users:
            print('User: ' + user.uid)
        # Get next batch of users.
        page = page.get_next_page()

Java

// Note, behind the scenes, the ListUsersPage retrieves 1000 Users at a time
// through the API
ListUsersPage  page = tenantAuth.listUsers(null);
for (ExportedUserRecord user : page.iterateAll()) {
  System.out.println("User: " + user.getUid());
}

// Iterating by pages 100 users at a time.
page = tenantAuth.listUsers(null, 100);
while (page != null) {
  for (ExportedUserRecord user : page.getValues()) {
    System.out.println("User: " + user.getUid());
  }

  page = page.getNextPage();
}

Baca dokumentasi Admin SDK mengenai mengelola pengguna untuk mempelajari lebih lanjut.

Mengimpor pengguna

Anda dapat menggunakan Admin SDK untuk mengimpor pengguna secara massal ke tenant tertentu dengan hak istimewa yang ditingkatkan. Hal ini menawarkan banyak manfaat, seperti kemampuan untuk memigrasikan pengguna dari produk Identity Platform lainnya, dari tenant lain, atau dari sistem autentikasi eksternal menggunakan algoritma hashing yang berbeda. Anda juga dapat mengimpor pengguna dengan penyedia gabungan (seperti SAML dan OIDC) serta klaim kustom secara langsung secara massal.

Untuk memulai, dapatkan instance TenantAwareAuth untuk tenant yang sesuai:

Node.js

const tenantAuth = admin.auth().tenantManager().authForTenant('TENANT-ID');

Python

tenant_client = tenant_mgt.auth_for_tenant('TENANT-ID')

Java

TenantAwareFirebaseAuth tenantAuth = FirebaseAuth.getInstance().getTenantManager()
    .getAuthForTenant("TENANT-ID");

Anda dapat mengimpor hingga 1.000 pengguna sekaligus menggunakan algoritma hashing tertentu.

Node.js

tenantAuth.importUsers([{
  uid: 'uid1',
  email: 'user1@example.com',
  // Must be provided in a byte buffer.
  passwordHash: Buffer.from('password-hash-1'),
  // Must be provided in a byte buffer.
  passwordSalt: Buffer.from('salt1')
},
{
  uid: 'uid2',
  email: 'user2@example.com',
  // Must be provided in a byte buffer.
  passwordHash: Buffer.from('password-hash-2'),
  // Must be provided in a byte buffer.
  passwordSalt: Buffer.from('salt2')

}], {
  hash: {
    algorithm: 'HMAC_SHA256',
    // Must be provided in a byte buffer.
    key: Buffer.from('secret')
  }
})
.then((results) => {
  results.errors.forEach(function(indexedError) {
  console.log('Error importing user ' + indexedError.index);
  });
})
.catch((error) => {
  console.log('Error importing users:', error);
});

Python

users = [
    auth.ImportUserRecord(
        uid='uid1',
        email='user1@example.com',
        password_hash=b'password_hash_1',
        password_salt=b'salt1'
    ),
    auth.ImportUserRecord(
        uid='uid2',
        email='user2@example.com',
        password_hash=b'password_hash_2',
        password_salt=b'salt2'
    ),
]

hash_alg = auth.UserImportHash.hmac_sha256(key=b'secret')
try:
    result = tenant_client.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)

Java

List<ImportUserRecord> users = new ArrayList<>();
users.add(ImportUserRecord.builder()
    .setUid("uid1")
    .setEmail("user1@example.com")
    .setPasswordHash("password-hash-1".getBytes())
    .setPasswordSalt("salt1".getBytes())
    .build());
users.add(ImportUserRecord.builder()
    .setUid("uid2")
    .setEmail("user2@example.com")
    .setPasswordHash("password-hash-2".getBytes())
    .setPasswordSalt("salt2".getBytes())
    .build());
UserImportHash hmacSha256 = HmacSha256.builder()
    .setKey("secret".getBytes())
    .build();
UserImportResult result = tenantAuth.importUsers(users, UserImportOptions.withHash(hmacSha256));

for (ErrorInfo error : result.getErrors()) {
  System.out.println("Failed to import user: " + error.getReason());
}

tenantId akan ditetapkan ke tenantAuth.tenantId untuk semua pengguna yang diimpor.

Pengguna tanpa sandi juga dapat diimpor ke tenant tertentu. Pengguna ini dapat diimpor dengan penyedia gabungan dan klaim kustom.

Node,js

tenantAuth.importUsers([{
  uid: 'some-uid',
  displayName: 'John Doe',
  email: 'johndoe@acme.com',
  photoURL: 'http://www.example.com/12345678/photo.png',
  emailVerified: true,
  phoneNumber: '+11234567890',
  // Set this user as admin.
  customClaims: {admin: true},
  // User with SAML provider.
  providerData: [{
    uid: 'saml-uid',
    email: 'johndoe@acme.com',
    displayName: 'John Doe',
    photoURL: 'http://www.example.com/12345678/photo.png',
    providerId: 'saml.acme'
  }]
}])
.then(function(results) {
  results.errors.forEach(function(indexedError) {
  console.log('Error importing user ' + indexedError.index);
  });
})
.catch(function(error) {
  console.log('Error importing users:', error);
});

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 SAML provider
            auth.UserProvider(
                uid='saml-uid',
                email='johndoe@gmail.com',
                display_name='John Doe',
                photo_url='http://www.example.com/12345678/photo.png',
                provider_id='saml.acme'
            )
        ],
    ),
]
try:
    result = tenant_client.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)

Java

List<ImportUserRecord> users = new ArrayList<>();
users.add(ImportUserRecord.builder()
    .setUid("some-uid")
    .setDisplayName("John Doe")
    .setEmail("johndoe@acme.com")
    .setPhotoUrl("https://www.example.com/12345678/photo.png")
    .setEmailVerified(true)
    .setPhoneNumber("+11234567890")
    // Set this user as admin.
    .putCustomClaim("admin", true)
    // User with SAML provider.
    .addUserProvider(UserProvider.builder()
        .setUid("saml-uid")
        .setEmail("johndoe@acme.com")
        .setDisplayName("John Doe")
        .setPhotoUrl("https://www.example.com/12345678/photo.png")
        .setProviderId("saml.acme")
        .build())
    .build());

UserImportResult result = tenantAuth.importUsers(users);

for (ErrorInfo error : result.getErrors()) {
  System.out.println("Failed to import user: " + error.getReason());
}

Lihat Mengimpor pengguna di dokumentasi Admin SDK untuk mempelajari lebih lanjut.

Verifikasi identitas (IDV)

Ketika aplikasi klien Identity Platform berkomunikasi dengan server backend khusus, pengguna yang sedang login harus diidentifikasi di server tersebut. Hal ini dapat dilakukan secara aman dengan mengirimkan token ID pengguna setelah berhasil login menggunakan koneksi yang aman ke server Anda. Selanjutnya, server dapat memverifikasi integritas dan keaslian token ID.

Admin SDK memiliki metode bawaan untuk memverifikasi dan mendekode token ID untuk tenant tertentu.

Setelah berhasil memproses login pengguna ke tenant tertentu dari klien, ambil token ID pengguna menggunakan SDK Klien:

auth.tenantId = 'TENANT-ID';
auth.signInWithEmailAndPassword('user@example.com', 'password')
  .then((userCredential) => {
    return userCredential.user.getIdToken();
  })
  .then((idToken) => {
    // Send the ID token to server for verification. ID token should be scoped to TENANT-ID.
  });

Buat instance TenantAwareAuth di server:

Node.js

const tenantAuth = admin.auth().tenantManager().authForTenant('TENANT-ID');

Python

tenant_client = tenant_mgt.auth_for_tenant('TENANT-ID')

Java

TenantAwareFirebaseAuth tenantAuth = FirebaseAuth.getInstance().getTenantManager()
    .getAuthForTenant("TENANT-ID");

Kemudian, Anda dapat memverifikasi token ID untuk tenant tersebut:

Node.js

// idToken comes from the client app
tenantAuth.verifyIdToken(idToken)
  .then((decodedToken) => {
    let uid = decodedToken.uid;
    // This should be set to TENANT-ID. Otherwise auth/mismatching-tenant-id error thrown.
    console.log(decodedToken.firebase.tenant);
    // ...
  }).catch((error) => {
    // Handle error
  });

Resource sisi server mungkin dapat diakses oleh beberapa tenant dengan tingkat akses yang berbeda. Dalam hal ini, karena ID tenant mungkin tidak diketahui sebelumnya, token ID dapat diverifikasi di level project terlebih dahulu.

admin.auth().verifyIdToken(idToken)
  .then((decodedToken) => {
    if (decodedToken.firebase.tenant === 'TENANT-ID1') {
      // Allow appropriate level of access for TENANT-ID1.
    } else if (decodedToken.firebase.tenant === 'TENANT-ID2') {
      // Allow appropriate level of access for TENANT-ID2.
    } else {
      // Block access for all other tenants.
      throw new Error('Access not allowed.');
    }
  }).catch((error) => {
    // Handle error
  });

Python

	# id_token comes from the client app
    try:
        decoded_token = tenant_client.verify_id_token(id_token)

        # This should be set to TENANT-ID. Otherwise TenantIdMismatchError error raised.
        print('Verified ID token from tenant:', decoded_token['firebase']['tenant'])
    except tenant_mgt.TenantIdMismatchError:
        # Token revoked, inform the user to reauthenticate or signOut().
        pass

Java

try {
  // idToken comes from the client app
  FirebaseToken token = tenantAuth.verifyIdToken(idToken);
  // TenantId on the FirebaseToken should be set to TENANT-ID.
  // Otherwise "tenant-id-mismatch" error thrown.
  System.out.println("Verified ID token from tenant: " + token.getTenantId());
} catch (FirebaseAuthException e) {
  System.out.println("error verifying ID token: " + e.getMessage());
}

Baca dokumentasi Admin SDK tentang memverifikasi token ID untuk mempelajari lebih lanjut.

Mengelola sesi pengguna

Sesi Identity Platform berlangsung lama. Setiap kali pengguna login, kredensial pengguna tersebut akan diverifikasi di server Identity Platform, lalu ditukar dengan token ID yang memiliki masa aktif singkat dan token refresh yang memiliki masa aktif lama. Token ID berlaku selama satu jam. Token refresh tidak memiliki masa berlaku, kecuali jika pengguna dinonaktifkan, dihapus, atau mengalami perubahan akun yang besar (seperti email atau pembaruan sandi).

Dalam beberapa kasus, token refresh pengguna mungkin perlu dicabut karena alasan keamanan, seperti pengguna melaporkan perangkat yang hilang atau dicuri, penemuan kerentanan umum dalam aplikasi, atau kebocoran token aktif dalam skala besar. Admin SDK menyediakan API untuk mencabut semua token refresh yang dikeluarkan untuk pengguna yang ditentukan dari tenant tertentu.

Untuk memulai, Anda memerlukan instance TenantAwareAuth:

Node.js

const tenantAuth = admin.auth().tenantManager().authForTenant('TENANT-ID');

Python

tenant_client = tenant_mgt.auth_for_tenant('TENANT-ID')

Java

TenantAwareFirebaseAuth tenantAuth = FirebaseAuth.getInstance().getTenantManager()
    .getAuthForTenant("TENANT-ID");

Token refresh kemudian dapat dicabut dengan menetapkan uid pengguna tersebut:

Node.js

// Revoke all refresh tokens for a specified user in a specified tenant for whatever reason.
// Retrieve the timestamp of the revocation, in seconds since the epoch.
tenantAuth.revokeRefreshTokens(uid)
  .then(() => {
    return tenantAuth.getUser(uid);
  })
  .then((userRecord) => {
    return new Date(userRecord.tokensValidAfterTime).getTime() / 1000;
  })
  .then((timestamp) => {
    console.log('Tokens revoked at: ', timestamp);
  });

Python

	# Revoke all refresh tokens for a specified user in a specified tenant for whatever reason.
	# Retrieve the timestamp of the revocation, in seconds since the epoch.
    tenant_client.revoke_refresh_tokens(uid)

    user = tenant_client.get_user(uid)
    # Convert to seconds as the auth_time in the token claims is in seconds.
    revocation_second = user.tokens_valid_after_timestamp / 1000
    print('Tokens revoked at: {0}'.format(revocation_second))

Java

// Revoke all refresh tokens for a specified user in a specified tenant for whatever reason.
// Retrieve the timestamp of the revocation, in seconds since the epoch.
tenantAuth.revokeRefreshTokens(uid);

// accessing the user's TokenValidAfter
UserRecord user = tenantAuth.getUser(uid);

long timestamp = user.getTokensValidAfterTimestamp() / 1000;
System.out.println("the refresh tokens were revoked at: " + timestamp + " (UTC seconds)");

Setelah token refresh dicabut, tidak ada token ID baru yang dapat dikeluarkan untuk pengguna tersebut hingga mereka melakukan autentikasi ulang. Namun, token ID yang ada akan tetap aktif hingga waktu habis masa berlakunya normalnya (satu jam).

Anda dapat memverifikasi bahwa token ID valid yang belum habis masa berlakunya tidak dicabut dengan menentukan parameter checkRevoked opsional; metode ini akan memeriksa apakah token dicabut setelah integritas dan keasliannya diverifikasi.

Node.js

// Verify the ID token for a specific tenant while checking if the token is revoked by passing
// checkRevoked true.
let checkRevoked = true;
tenantAuth.verifyIdToken(idToken, checkRevoked)
  .then(payload => {
    // Token is valid.
  })
  .catch(error => {
    if (error.code == 'auth/id-token-revoked') {
      // Token has been revoked. Inform the user to re-authenticate or
      // signOut() the user.
    } else {
      // Token is invalid.
    }
  });

Python

	# Verify the ID token for a specific tenant while checking if the token is revoked.
    try:
        # Verify the ID token while checking if the token is revoked by
        # passing check_revoked=True.
        decoded_token = tenant_client.verify_id_token(id_token, check_revoked=True)
        # Token is valid and not revoked.
        uid = decoded_token['uid']
    except tenant_mgt.TenantIdMismatchError:
        # Token belongs to a different tenant.
        pass
    except auth.RevokedIdTokenError:
        # Token revoked, inform the user to reauthenticate or signOut().
        pass
    except auth.UserDisabledError:
        # Token belongs to a disabled user record.
        pass
    except auth.InvalidIdTokenError:
        # Token is invalid
        pass

Java

// Verify the ID token for a specific tenant while checking if the token is revoked.
boolean checkRevoked = true;
try {
  FirebaseToken token = tenantAuth.verifyIdToken(idToken, checkRevoked);
  System.out.println("Verified ID token for: " + token.getUid());
} catch (FirebaseAuthException e) {
  if ("id-token-revoked".equals(e.getErrorCode())) {
    // Token is revoked. Inform the user to re-authenticate or signOut() the user.
  } else {
    // Token is invalid
  }
}

Lihat dokumentasi Admin SDK mengenai mengelola sesi untuk mempelajari lebih lanjut.

Mengontrol akses dengan klaim kustom

Admin SDK mendukung penentuan atribut khusus pada akun pengguna untuk tenant tertentu. Atribut ini memungkinkan Anda menerapkan berbagai strategi kontrol akses, seperti kontrol akses berbasis peran. Atribut ini dapat digunakan untuk memberi pengguna berbagai tingkat akses yang diterapkan oleh aturan keamanan aplikasi.

Untuk memulai, dapatkan instance TenantAwareAuth untuk tenant yang sesuai:

Node.js

const tenantAuth = admin.auth().tenantManager().authForTenant('TENANT-ID');

Python

tenant_client = tenant_mgt.auth_for_tenant('TENANT-ID')

Java

TenantAwareFirebaseAuth tenantAuth = FirebaseAuth.getInstance().getTenantManager()
    .getAuthForTenant("TENANT-ID");

Klaim kustom dapat berisi data sensitif, sehingga hanya boleh ditetapkan dari lingkungan server dengan hak istimewa menggunakan Admin SDK.

Node.js

// Set admin privilege on the user corresponding to uid for a specific tenant.
tenantAuth.setCustomUserClaims(uid, {admin: true}).then(() => {
  // The new custom claims will propagate to the user's ID token the
  // next time a new one is issued.
});

Python

# Set admin privilege on the user corresponding to uid.
tenant_client.set_custom_user_claims(uid, {'admin': True})
# The new custom claims will propagate to the user's ID token the
# next time a new one is issued.

Java

// Set admin privilege on the user corresponding to uid in a specific tenant.
Map<String, Object> claims = new HashMap<>();
claims.put("admin", true);
tenantAuth.setCustomUserClaims(uid, claims);
// The new custom claims will propagate to the user's ID token the
// next time a new one is issued.

Atribut khusus yang baru ditetapkan akan muncul di atribut level teratas payload token saat pengguna login atau memperbarui token ID-nya pada sesi yang sudah ada. Pada contoh sebelumnya, token ID berisi klaim tambahan: {admin: true}.

Setelah memverifikasi token ID dan mendekode payload-nya, klaim kustom tambahan dapat diperiksa untuk menerapkan kontrol akses.

Node.js

// Verify the ID token first.
tenantAuth.verifyIdToken(idToken).then((claims) => {
  if (claims.admin === true) {
    // Allow access to requested admin resource.
  }
});

Python

# Verify the ID token first.
claims = tenant_client.verify_id_token(id_token)
if claims['admin'] is True:
    # Allow access to requested admin resource.
    pass

Java

// Verify the ID token first.
FirebaseToken token = tenantAuth.verifyIdToken(idToken);
if (Boolean.TRUE.equals(token.getClaims().get("admin"))) {
  //Allow access to requested admin resource.
}
// Verify the ID token first.
FirebaseToken decoded = tenantAuth.verifyIdToken(idToken);
if (Boolean.TRUE.equals(decoded.getClaims().get("admin"))) {
  // Allow access to requested admin resource.
}

Klaim kustom bagi pengguna yang ada untuk tenant tertentu juga tersedia sebagai properti pada data pengguna.

Node.js

// Lookup the user associated with the specified uid.
tenantAuth.getUser(uid).then((userRecord) => {
  // The claims can be accessed on the user record.
  console.log(userRecord.customClaims.admin);
});

Python

	# Lookup the user associated with the specified uid.
    user = tenant_client.get_user(uid)

	# The claims can be accessed on the user record.
    print(user.custom_claims.get('admin'))

Java

// Lookup the user associated with the specified uid in a specific tenant.
UserRecord user = tenantAuth.getUser(uid);
System.out.println(user.getCustomClaims().get("admin"));

Lihat dokumentasi Admin SDK tentang Klaim kustom untuk mempelajari lebih lanjut.

Dengan menggunakan Identity Platform Client SDK, Anda dapat mengirim email tenant tertentu yang berisi link untuk reset sandi, verifikasi alamat email, dan login dengan email kepada pengguna. Email ini dikirim oleh Google dan memiliki kemampuan penyesuaian yang terbatas.

Dengan Admin SDK, Anda dapat membuat link ini secara terprogram dalam cakupan tenant tertentu.

Untuk memulai, dapatkan instance TenantAwareAuth untuk tenant yang sesuai:

Node.js

const tenantAuth = admin.auth().tenantManager().authForTenant('TENANT-ID');

Python

tenant_client = tenant_mgt.auth_for_tenant('TENANT-ID')

Java

TenantAwareFirebaseAuth tenantAuth = FirebaseAuth.getInstance().getTenantManager()
    .getAuthForTenant("TENANT-ID");

Contoh berikut menunjukkan cara membuat link untuk memverifikasi email pengguna untuk tenant tertentu:

Node.js

const actionCodeSettings = {
  // URL you want to redirect back to. The domain (www.example.com) for
  // this URL must be whitelisted in the Cloud console.
  url: 'https://www.example.com/checkout?cartId=1234',
  // This must be true for email link sign-in.
  handleCodeInApp: true,
  iOS: {
    bundleId: 'com.example.ios'
  },
  android: {
    packageName: 'com.example.android',
    installApp: true,
    minimumVersion: '12'
  },
  // FDL custom domain.
  dynamicLinkDomain: 'coolapp.page.link'
};

// Admin SDK API to generate the email verification link.
const userEmail = 'user@example.com';
tenantAuth.generateEmailVerificationLink(userEmail, actionCodeSettings)
  .then((link) => {
    // Construct email verification template, embed the link and send
    // using custom SMTP server.
    return sendCustomVerificationEmail(userEmail, displayName, link);
  })
  .catch((error) => {
    // Some error occurred.
  });

Python

action_code_settings = auth.ActionCodeSettings(
    url='https://www.example.com/checkout?cartId=1234',
    handle_code_in_app=True,
    ios_bundle_id='com.example.ios',
    android_package_name='com.example.android',
    android_install_app=True,
    android_minimum_version='12',
    # FDL custom domain.
    dynamic_link_domain='coolapp.page.link',
)

email = 'user@example.com'
link = tenant_client.generate_email_verification_link(email, action_code_settings)
# Construct email from a template embedding the link, and send
# using a custom SMTP server.
send_custom_email(email, link)

Java

ActionCodeSettings actionCodeSettings = ActionCodeSettings.builder()
    // URL you want to redirect back to. The domain (www.example.com) for
    // this URL must be whitelisted in the GCP Console.
    .setUrl("https://www.example.com/checkout?cartId=1234")
    // This must be true for email link sign-in.
    .setHandleCodeInApp(true)
    .setIosBundleId("com.example.ios")
    .setAndroidPackageName("com.example.android")
    .setAndroidInstallApp(true)
    .setAndroidMinimumVersion("12")
    // FDL custom domain.
    .setDynamicLinkDomain("coolapp.page.link")
    .build();

String link = tenantAuth.generateEmailVerificationLink(email, actionCodeSettings);

// Construct email verification template, embed the link and send
// using custom SMTP server.
sendCustomEmail(email, displayName, link);

Mekanisme serupa tersedia untuk membuat reset sandi dan link login berbasis email. Perhatikan bahwa saat membuat link tindakan email dalam konteks tenant, ID tenant harus diurai dari link dan ditetapkan pada instance Auth klien sebelum kode dapat diterapkan.

const actionCodeUrl = firebase.auth.ActionCodeURL.parseLink(window.location.href);
// A one-time code, used to identify and verify a request.
const code = actionCodeUrl.code;
// The tenant ID being used to trigger the email action.
const tenantId = actionCodeUrl.tenantId;
auth.tenantId = tenantId;

// Apply the action code.
auth.applyActionCode(actionCode)
  .then(() => {
    // User's email is now verified.
  })
  .catch((error) => {
    // Handle error.
  });

Lihat Link tindakan email dalam dokumentasi Admin SDK untuk mempelajari lebih lanjut.

Pesan error

Tabel berikut mencantumkan pesan error umum yang mungkin Anda temui.

Kode error Deskripsi dan Langkah Penyelesaian
auth/billing-not-enabled Fitur ini mengharuskan penagihan diaktifkan.
auth/invalid-display-name Bidang displayName harus berupa string yang valid.
auth/invalid-name Nama resource yang diberikan tidak valid.
auth/invalid-page-token Token halaman harus berupa string yang tidak kosong dan valid.
auth/invalid-project-id Project induk tidak valid. Project induk tidak mengaktifkannya, atau tidak mengaktifkan multi-tenancy.
auth/invalid-tenant-id ID tenant harus berupa string yang tidak kosong dan valid.
auth/mismatching-tenant-id ID tenant pengguna tidak cocok dengan ID tenant TenantAwareAuth saat ini.
auth/missing-display-name Resource yang dibuat atau diedit tidak memiliki nama tampilan yang valid.
auth/insufficient-permission Pengguna tidak memiliki izin yang memadai untuk mengakses resource yang diminta atau untuk menjalankan operasi tenant tertentu.
auth/quota-exceeded Kuota project untuk operasi yang ditentukan telah terlampaui.
auth/tenant-not-found Tidak ada tenant yang sesuai dengan ID yang diberikan.
auth/unsupported-tenant-operation Operasi ini tidak didukung dalam konteks multi-tenant.
auth/invalid-testing-phone-number Nomor telepon pengujian yang tidak valid atau kode pengujian yang tidak valid diberikan.
auth/test-phone-number-limit-exceeded Jumlah maksimum pasangan kode dan nomor telepon pengujian yang diizinkan telah terlampaui.