ניהול טננטים של Identity Platform באופן פרוגרמטי

במאמר הזה מוסבר איך להשתמש ב-SDK לאדמינים של Identity Platform כדי לנהל דיירים (tenants) ומשתמשים שלהם באופן פרוגרמטי. הנה כמה פעולות שאפשר לבצע כאדמינים:

  • ניהול משתמשים: יצירה, עדכון, מחיקה ורישום של משתמשים לדייר ספציפי.

  • אימות זהות: זיהוי משתמשים באפליקציה כדי להגביל את הגישה למשאבים בשרת שלכם.

  • ייבוא משתמשים: העברת משתמשים ממערכת אימות חיצונית או מפרויקט או מדייר אחרים ב-Identity Platform.

  • בקרת גישה באמצעות טענות מותאמות אישית: הגדרת מאפיינים מותאמים אישית בחשבונות משתמשים לדייר ספציפי, והטמעה של אסטרטגיות שונות של בקרת גישה, כמו בקרת גישה מבוססת-תפקידים.

  • ניהול סשנים של משתמשים: ביטול טוקנים לרענון של משתמש בדייר ספציפי.

  • קישורים לפעולות באימייל: יצירת קישורים מותאמים אישית באימייל לאיפוס סיסמה, לכניסה באמצעות קישור באימייל ולאימות אימייל למשתמשים בדייר ספציפי.

  • ניהול דיירים: יצירה, הצגה, קבלת מידע, עדכון ומחיקה של דיירים בפרויקט ספציפי ב-Identity Platform.

  • ניהול ספקי OIDC ו-SAML בדיירים: ניהול תצורות של OIDC ו-SAML בדייר ספציפי באופן פרוגרמטי.

לפני שמתחילים

תכונות נתמכות

בטבלה הבאה מפורטות התכונות שנתמכות על ידי כל ערכת SDK בסביבה מרובת דיירים:

תכונה Node.js Java Python Go C#‎
הנפקת טוקנים בהתאמה אישית
אימות של טוקנים של מזהים
ניהול משתמשים
שליטה בגישה באמצעות טענות בהתאמה אישית
ביטול אסימוני רענון
ייבוא משתמשים
יצירת קישורים לפעולות באימייל
אימות רב-שלבי
ניהול הגדרות של ספקי SAML/OIDC
ניהול קובצי Cookie זמניים

בטבלה הבאה מפורטות שיטות הכניסה שאפשר להגדיר באמצעות SDK לאדמינים ומסוף Google Cloud בהקשר ספציפי לדייר:

תכונה מסוףGoogle Cloud Admin SDK
אימייל
OIDC
SAML
רשתות חברתיות
טלפון
אימות רב-שלבי
אנונימי

ניהול דיירים

באמצעות SDK לאדמינים, אתם יכולים לנהל דיירים באופן פרוגרמטי מסביבת שרת מאובטחת במקום להשתמש במסוף Google Cloud . הפעולות האלה כוללות את היכולת ליצור דיירים, להציג אותם ברשימה, לקבל אותם, לשנות אותם או למחוק אותם.

כל דייר מכיל ספקי זהויות, הגדרות וקבוצות משתמשים משלו. פעולות ניהול של הגדרות הדייר (CRUD) זמינות ממופע פרויקט האב באמצעות admin.auth().tenantManager().

הגדרת דייר מספקת מידע על דייר, כמו שם התצוגה, מזהה הדייר והגדרת אימות האימייל.

כל ההגדרות האחרות (כמו דומיינים ברשימת ההיתרים וכתובות URI מאומתות להפניה אוטומטית) של דייר עוברות בירושה מהפרויקט הראשי. צריך לנהל את המכשירים האלה באמצעות מסוף Google Cloud .

כדי לבצע פעולות כמו ניהול משתמשים ספציפי לדייר, הגדרת ספקי OIDC/SAML ויצירת קישור לאימייל, תצטרכו מופע TenantAwareAuth עבור הדייר היעד (שמזוהה באמצעות tenantId הייחודי שלו).

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);

כל הקריאות לממשקי ה-API לניהול משתמשים, לממשקי ה-API לניהול ספקי OIDC/SAML ולממשקי ה-API ליצירת קישורי אימייל יתבצעו במסגרת הדייר הזה (באמצעות מופע TenantAwareAuth שלו).

קבלת דייר קיים

‫SDK לאדמינים מספק את השיטה getTenant(), שמביאה מידע על דייר (tenant) על סמך tenantId (מזהה ייחודי של הדייר).

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('Retrieved tenant:', tenant.tenant_id)

Java

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

השיטה הזו מחזירה אובייקט Tenant שמתאים ל-tenantId. אם הערך של tenantId שסופק לא שייך לדייר קיים, אובייקט ה-promise שמוחזר נדחית עם השגיאה auth/tenant-not-found.

חשוב לא להתבלבל בין מופע של Tenant לבין אובייקט TenantAwareAuth. הפונקציה authInstance.tenantManager().authForTenant() מחזירה מופע של TenantAwareAuth שמרחיב את BaseAuth. הכיתה Auth מרחיבה גם את BaseAuth. ‫BaseAuth מספקת ממשקי API לניהול משתמשים ולהגדרת ספקי OIDC/SAML בהקשרים שונים. ב-Auth, ההקשר הוא ברמת פרויקט האב. במקרה של TenantAwareAuth, ההקשר הוא ברמת הדייר (הדייר נקבע לפי מזהה הדייר). השיטה getTenant() תפתור בעיות עם מידע בסיסי על הדייר (כמו מזהה הדייר, שם התצוגה והגדרות ספק האימייל), אבל כדי לקרוא לממשקי API בדייר הזה, צריך להשתמש ב-authForTenant(tenantFromGetTenant.tenantId).

יצירת דייר

משתמשים בשיטה createTenant() כדי ליצור הגדרות חדשות לדייר:

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());

אפשר לציין כל שילוב של המאפיינים האלה:

מאפיין (property) סוג תיאור
displayName
string
    
השם המוצג של הדייר. השם צריך לכלול בין 4 ל-20 תווים – רק אותיות, ספרות ומקפים, ולהתחיל באות.
emailSignInConfig
{
  enable: boolean,
  passwordRequired: boolean
}
    
הגדרות הספק לכניסה באמצעות אימייל. זה כולל את השאלה אם ספק האימייל מופעל, ואם נדרשת סיסמה לכניסה לאימייל. אם לא נדרשת סיסמה, אפשר להיכנס לחשבון באמצעות קישור שנשלח באימייל.
multiFactorConfig
{
  state: 'DISABLED' | 'ENABLED',
  factorIds: string[]
}
    
האם אימות רב-שלבי מופעל לדייר, ואילו סוגי גורמים מותרים. בשלב הזה, מזהה הגורם הנתמך היחיד הוא phone.
testPhoneNumbers
{
  string: string
}
  
מפה של מספרי טלפון וקודי האימות הרב-שלבי המשויכים להם לצורך רישום לבדיקות. אפשר להוסיף עד 10 ערכים. כדי להסיר את כל מספרי הטלפון לבדיקה, מגדירים את השדה הזה לערך null.

השיטה מחזירה אובייקט Tenant של הדייר החדש שנוצר.

עדכון של דייר

משתמשים בשיטה updateTenant() כדי לשנות את הנתונים של דייר קיים. תצטרכו לציין את tenantId, יחד עם המאפיינים שרוצים לעדכן עבור הדייר הזה.

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() מקבל את אותם מאפיינים כמו createTenant(). כל המאפיינים הם אופציונליים. אם לא מציינים מאפיין, הערך הקיים לא ישתנה.

השיטה מחזירה אובייקט Tenant מעודכן בסיום. אם הערך tenantId שסופק לא שייך לדייר קיים, אובייקט ה-promise שמוחזר נדחית עם השגיאה auth/tenant-not-found.

מחיקת דייר

אפשר למחוק דייר באמצעות tenantId:

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);

השיטה מחזירה תוצאה ריקה כשהמחיקה מסתיימת בהצלחה. אם הערך של tenantId שסופק לא שייך לדייר קיים, אובייקט ה-promise שמוחזר נדחית עם השגיאה auth/tenant-not-found.

דיירים בנכס

כדי להציג רשימה של דיירים קיימים, משתמשים בשיטה listTenants():

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());
}

כל קבוצת תוצאות מכילה רשימה של דיירים, בנוסף לאסימון של הדף הבא כדי להציג את הקבוצה הבאה של דיירים. אחרי שכל הדיירים מוצגים, לא מוחזר אף pageToken.

אם לא מציינים את השדה maxResults, ברירת המחדל היא 1,000 דיירים לכל חבילה. זה גם המספר המקסימלי של דיירים שאפשר להציג בבת אחת. כל ערך שגדול מהערך המקסימלי יגרום לשגיאת ארגומנט. אם לא מציינים pageToken, השיטה תציג רשימה של דיירים מההתחלה.

ניהול ספקי SAML ו-OIDC באופן פרוגרמטי

‫Admin SDK מספק ממשקי API לניהול הגדרות של ספק OpenID Connect ‏(OIDC) ו-Security Assertion Markup Language ‏ (SAML) 2.0 באופן פרוגרמטי מסביבת שרת מאובטחת.

באמצעות SDK לאדמינים, אתם יכולים לנהל את הספקים האלה לדייר ספציפי. זה דומה לניהול ספקי OIDC ו-SAML ברמת הפרויקט.

כדי לנהל ספקים לדייר, קודם צריך ליצור מופע 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");

לאחר מכן תוכלו לבצע פעולות נפוצות, כמו יצירה, שינוי או מחיקה של ספקים לדייר.

יצירת ספק

הקוד הבא מראה איך ליצור ספק SAML לדייר:

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());

שינוי ספק

הקוד הבא מראה איך לשנות ספק:

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());

קבלת ספק

הקוד הבא מראה איך לאחזר את הגדרות הספק לדייר ספציפי באמצעות מזהה הספק שלו:

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());

ספקי רשימות

הקוד הבא מראה איך לרשום את הגדרות הפלאגין שמתממשק עם שירותים חיצוניים לדייר (tenant) נתון:

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());
}

מחיקת ספק

הקוד הבא מראה איך מוחקים ספק:

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");

הניהול של ספקי OIDC מתבצע באופן דומה לניהול של ספקי OIDC ברמת הפרויקט, אבל אפשר לנהל אותם ממופע TenantAwareAuth תואם, ולא ממופע Auth ברמת הפרויקט.

מידע נוסף זמין במאמר בנושא ניהול ספקי SAML ו-OIDC באופן פרוגרמטי.

ניהול משתמשים ספציפיים לדייר

אתם יכולים להשתמש ב-SDK לאדמינים כדי ליצור, לאחזר, לעדכן, למחוק ולרשום את כל המשתמשים בדייר ספציפי.

כדי להתחיל, צריך מכונה (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");

קבלת משתמש

אפשר לאחזר משתמש ספציפי לדייר עם מזהה 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());

אפשר גם לזהות משתמש לפי כתובת האימייל שלו:

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());

יצירת משתמש

משתמשים בשיטה createUser() כדי ליצור משתמשים חדשים לדייר ספציפי. כשיוצרים משתמש חדש, אפשר לציין uid, אבל זה לא חובה. אם לא מציינים, Identity Platform יקצה מזהה ייחודי.

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());

שינוי משתמש

אפשר לשנות משתמשים קיימים על ידי ציון uid שלהם בשיטה 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());

מחיקת משתמש

בדוגמה הבאה אפשר לראות איך מוחקים משתמש על סמך uid שלו:

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);

הכנסת משתמשים לרשימה

כדי לאחזר רשימה מלאה של משתמשים לדייר ספציפי באצוות, משתמשים בשיטה listUsers(). כל חבילה תכיל רשימה של רשומות משתמשים, בנוסף לאסימון של הדף הבא אם יש עוד משתמשים.

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();
}

מידע נוסף זמין במאמרי התיעוד של SDK לאדמינים בנושא ניהול משתמשים.

ייבוא משתמשים

אתם יכולים להשתמש ב-SDK לאדמינים כדי לייבא משתמשים בכמות גדולה לדייר ספציפי עם הרשאות מורחבות. השימוש ב-Identity Platform מציע יתרונות רבים, כמו האפשרות להעביר משתמשים ממוצר אחר של Identity Platform, מדייר אחר או ממערכת אימות חיצונית באמצעות אלגוריתם גיבוב שונה. אפשר גם לייבא משתמשים עם ספקים מאוחדים (כמו SAML ו-OIDC) ותביעות מותאמות אישית ישירות בכמות גדולה.

כדי להתחיל, צריך לקבל מכונת 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");

אפשר לייבא עד 1,000 משתמשים בכל פעם באמצעות אלגוריתם גיבוב ספציפי.

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 של כל המשתמשים שיובאו יוגדר לערך tenantAuth.tenantId.

אפשר גם לייבא משתמשים ללא סיסמאות לדייר ספציפי. אפשר לייבא את המשתמשים האלה באמצעות ספקי זהויות מאוחדים ומידע מותאם אישית.

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());
}

מידע נוסף זמין במאמר ייבוא משתמשים במסמכי התיעוד של SDK לאדמינים.

אימות זהות

כשלקוח של אפליקציית Identity Platform מתקשר עם שרת קצה עורפי בהתאמה אישית, צריך לזהות בשרת הזה את המשתמש שמחובר כרגע. אפשר לעשות את זה בצורה מאובטחת על ידי שליחת אסימון הזהות של המשתמש אחרי כניסה מוצלחת, באמצעות חיבור מאובטח לשרת. לאחר מכן השרת יכול לאמת את השלמות והאותנטיות של אסימון ה-ID.

ל-SDK לאדמינים יש שיטה מובנית לאימות ולפענוח של אסימוני מזהה עבור דייר ספציפי.

אחרי שהמשתמש נכנס בהצלחה לדייר ספציפי מהלקוח, צריך לאחזר את טוקן הזהות של המשתמש באמצעות Client SDK:

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.
  });

יוצרים מכונת 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");

אחר כך תוכלו לאמת את אסימון הזהות עבור הדייר הספציפי הזה:

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
  });

יכול להיות שלמשאב בצד השרת תהיה גישה לכמה דיירים עם רמות גישה שונות. במקרה הזה, יכול להיות שמזהה הדייר לא ידוע מראש, ולכן אפשר לאמת את טוקן הזהות ברמת הפרויקט.

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());
}

מידע נוסף זמין במאמר בנושא אימות אסימוני מזהה במסמכי התיעוד של SDK לאדמינים.

ניהול סשנים של משתמשים

הסשנים ב-Identity Platform הם ארוכים. בכל פעם שמשתמש מתחבר, פרטי הכניסה שלו מאומתים בשרת Identity Platform, ואז מוחלפים באסימון מזהה לטווח קצר ובאסימון רענון לטווח ארוך. אסימונים מזהים תקפים למשך שעה. תוקף של טוקנים לרענון אף פעם לא פג, אלא אם המשתמש מושבת, נמחק או עובר שינוי גדול בחשבון (כמו עדכון של כתובת אימייל או סיסמה).

במקרים מסוימים, יכול להיות שיהיה צורך לבטל את אסימון הרענון של משתמש מסיבות אבטחה, למשל אם המשתמש דיווח על מכשיר שאבד או נגנב, אם התגלתה פגיעות כללית באפליקציה או אם חלה דליפה רחבת היקף של אסימונים פעילים. ‫SDK לאדמינים מספק API לביטול כל אסימוני הרענון שהונפקו למשתמש ספציפי בדייר ספציפי.

כדי להתחיל, צריך מופע 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");

אחר כך אפשר לבטל את טוקני הרענון על ידי ציון ה-uid של המשתמש:

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(f'Tokens revoked at: {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)");

אחרי ביטול טוקנים לרענון, לא ניתן להנפיק טוקנים חדשים של מזהים עבור המשתמש עד שהוא יאומת מחדש. עם זאת, אסימונים מזהים קיימים יישארו פעילים עד לתאריך התפוגה שלהם (שעה אחת).

כדי לוודא שאסימון מזהה תקף שתוקפו לא פג לא בוטל, צריך לציין את הפרמטר האופציונלי checkRevoked. הפרמטר הזה בודק אם אסימון בוטל אחרי ששלמותו והאותנטיות שלו אומתו.

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
  }
}

מידע נוסף זמין בתיעוד של SDK לאדמינים בנושא ניהול סשנים.

שליטה בגישה באמצעות טענות בהתאמה אישית

‫SDK לאדמינים תומך בהגדרת מאפיינים בהתאמה אישית בחשבונות משתמשים לדייר ספציפי. המאפיינים האלה מאפשרים לכם ליישם אסטרטגיות שונות של בקרת גישה, כמו בקרת גישה מבוססת-תפקידים. אפשר להשתמש במאפיינים כדי לתת למשתמשים רמות גישה שונות שנאכפות על ידי כללי האבטחה של האפליקציה.

כדי להתחיל, צריך לקבל מופע 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");

טענות מותאמות אישית יכולות להכיל מידע אישי רגיש, ולכן צריך להגדיר אותן רק בסביבת שרת עם הרשאות מיוחדות באמצעות 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.

מאפיינים מותאמים אישית שהוגדרו לאחרונה יופיעו במאפיינים ברמה העליונה של מטען הייעודי (payload) של האסימון בפעם הבאה שהמשתמש ייכנס לחשבון או ירענן את אסימוני הזהות שלו בסשן קיים. בדוגמה הקודמת, טוקן ה-ID מכיל תביעה נוספת: {admin: true}.

אחרי שמאמתים את טוקן ה-ID ומפענחים את המטען הייעודי (payload) שלו, אפשר לבדוק את הטענות המותאמות אישית הנוספות כדי לאכוף את בקרת הגישה.

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.
}

טענות בהתאמה אישית למשתמש קיים בדייר ספציפי זמינות גם כמאפיין ברשומת המשתמש.

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"));

מידע נוסף זמין בתיעוד של SDK לאדמינים בנושא טענות מותאמות אישית.

באמצעות ערכות ה-SDK של Identity Platform Client, אתם יכולים לשלוח למשתמשים בדייר ספציפי הודעות אימייל עם קישורים שבהם הם יכולים להשתמש כדי לאפס סיסמאות, לאמת כתובות אימייל ולהיכנס באמצעות אימייל. האימיילים האלה נשלחים על ידי Google ואפשר להתאים אותם רק במידה מוגבלת.

באמצעות SDK לאדמינים, אפשר ליצור את הקישורים האלה באופן פרוגרמטי במסגרת של דייר ספציפי.

כדי להתחיל, צריך לקבל מופע 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");

בדוגמה הבאה אפשר לראות איך ליצור קישור לאימות כתובת אימייל של משתמש בדייר ספציפי:

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);

מנגנונים דומים זמינים ליצירת קישורים לאיפוס סיסמה ולכניסה באמצעות אימייל. שימו לב: כשיוצרים קישור לפעולה באימייל בהקשר של דייר, צריך לנתח את מזהה הדייר מהקישור ולהגדיר אותו במופע של הלקוח Auth לפני שאפשר להחיל את הקוד.

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.
  });

מידע נוסף זמין במאמר קישורים לפעולות באימייל במסמכי התיעוד של SDK לאדמינים.

הודעות שגיאה

בטבלה הבאה מפורטות הודעות שגיאה נפוצות שבהן אתם עשויים להיתקל.

קוד שגיאה תיאור ושלבים לפתרון
auth/billing-not-enabled כדי להשתמש בתכונה הזו צריך להפעיל את החיוב.
auth/invalid-display-name השדה displayName חייב להיות מחרוזת תקינה.
auth/invalid-name שם המשאב שצוין לא תקין.
auth/invalid-page-token טוקן הדף חייב להיות מחרוזת תקינה ולא ריקה.
auth/invalid-project-id פרויקט האב לא תקין. או שלא מופעלת בפרויקט ההורה תמיכה בריבוי דיירים, או שהיא לא הופעלה בו בעבר.
auth/invalid-tenant-id מזהה הדייר חייב להיות מחרוזת לא ריקה ותקינה.
auth/mismatching-tenant-id מזהה הדייר של המשתמש לא תואם למזהה הדייר הנוכחי של TenantAwareAuth.
auth/missing-display-name למשאב שנוצר או נערך חסר שם תצוגה תקין.
auth/insufficient-permission למשתמש אין מספיק הרשאות כדי לגשת למשאב המבוקש או כדי להפעיל את הפעולה הספציפית בדייר.
auth/quota-exceeded הייתה חריגה מהמכסה של הפרויקט לפעולה שצוינה.
auth/tenant-not-found אין דייר שמתאים למזהה שצוין.
auth/unsupported-tenant-operation הפעולה הזו לא נתמכת בהקשר של ריבוי דיירים.
auth/invalid-testing-phone-number צוין מספר טלפון לבדיקה או קוד בדיקה לא תקינים.
auth/test-phone-number-limit-exceeded חרגתם מהמספר המקסימלי של זוגות של קוד ומספר טלפון לבדיקה שמותר להשתמש בהם.