Gestione programmatica dei tenant di Identity Platform
Questo documento spiega come utilizzare l'SDK Admin di Identity Platform per gestire e ai loro utenti in modo programmatico. Alcune attività che puoi svolgere un amministratore include:
Gestione utenti: crea, aggiorna, elimina ed elenca gli utenti per uno specifico tenant.
Verifica dell'identità: identifica gli utenti di un'app da limitare l'accesso alle risorse sul tuo server.
Importare utenti:esegui la migrazione degli utenti da un sistema di autenticazione esterno in un altro progetto o tenant di Identity Platform.
Controllo dell'accesso con attestazioni personalizzate: definisci attributi personalizzati per l'utente. account per uno specifico tenant e implementare vari controllo dell'accesso come controllo dell'accesso basato sui ruoli.
Gestione delle sessioni utente:revoca i token di aggiornamento di un utente per uno specifico tenant.
Link di azione email: genera link email personalizzati per la reimpostazione della password. l'accesso tramite link email e la verifica email per gli utenti di un tenant specifico.
Gestione tenant: crea, elenca, recupera, aggiorna ed elimina i tenant per un un progetto Identity Platform specifico.
Gestione dei provider OIDC e SAML sui tenant: gestisci in modo programmatico Configurazioni OIDC e SAML su un tenant specificato.
Prima di iniziare
Installa l'SDK Admin per Node.js, Java, Python, Go o C#.
Abilita la multitenancy per Google Cloud progetto.
Funzionalità supportate
La tabella seguente elenca le funzionalità supportate da ogni SDK in un ambiente multi-tenant questo ambiente:
Funzionalità | Node.js | Java | Python | Vai | C# |
---|---|---|---|---|---|
Minting di token personalizzati | |||||
Verifica dei token ID | |||||
Gestire gli utenti | |||||
Controllo dell'accesso con rivendicazioni personalizzate | |||||
Revoca dei token di aggiornamento | |||||
Importazione degli utenti | |||||
Generazione di link di azione email in corso... | |||||
Autenticazione a più fattori | |||||
Gestione delle configurazioni dei provider SAML/OIDC | |||||
Gestione dei cookie di sessione |
La tabella seguente mostra quali metodi di accesso puoi configurare utilizzando il SDK Admin e console Google Cloud in un contesto specifico per il tenant:
Funzionalità | Console Google Cloud | SDK Admin |
---|---|---|
OIDC | ||
SAML | ||
Social | ||
Telefono | ||
Autenticazione a più fattori | ||
Anonimo |
Gestione degli inquilini
Con l'SDK Admin, puoi gestire i tenant in modo programmatico da un un ambiente server sicuro anziché utilizzare la console Google Cloud. Questo include la possibilità di creare, elencare, ottenere, modificare o eliminare i tenant.
Ogni tenant contiene i propri provider di identità, impostazioni e insiemi di utenti.
Le operazioni di gestione della configurazione tenant (CRUD) sono disponibili nell'istanza
di progetto utilizzando admin.auth().tenantManager()
.
Una configurazione tenant fornisce informazioni su un tenant, ad esempio il nome visualizzato, l'identificatore tenant e la configurazione dell'autenticazione email.
Tutte le altre impostazioni (ad esempio domini autorizzati e URI di reindirizzamento autenticati) di un tenant vengono ereditati dal progetto padre. Queste devono essere gestite utilizzando la console Google Cloud.
Per operazioni come la gestione utenti specifica per il tenant, la configurazione di OIDC/SAML
e la generazione di link via email, avrai bisogno di un'istanza TenantAwareAuth
per il tenant di destinazione (identificato dal suo tenantId
univoco).
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);
Tutte le chiamate alle API di gestione degli utenti, alle API di gestione dei provider OIDC/SAML e
le API di generazione dei link email rientreranno nell'ambito di questo tenant (utilizzando il suo
TenantAwareAuth
).
Recupero di un tenant esistente
L'SDK Admin fornisce il metodo getTenant()
, che recupera le informazioni
relative a un tenant in base al suo tenantId
(un identificatore univoco del 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());
Questo metodo restituisce un oggetto Tenant
corrispondente a tenantId
.
Se il valore tenantId
fornito non appartiene a un tenant esistente, il valore
la promessa viene rifiutata con un errore di auth/tenant-not-found
.
Fai attenzione a non confondere un'istanza Tenant
con una TenantAwareAuth
. authInstance.tenantManager().authForTenant()
restituisce un
TenantAwareAuth
istanza che si estende
BaseAuth
La Auth
Inoltre, una classe estende BaseAuth
.
BaseAuth
fornisce le API per gestire gli utenti e configurare i provider OIDC/SAML
in contesti diversi. Per Auth
, il contesto è a livello del progetto padre.
Per TenantAwareAuth
, il contesto è a livello di tenant (il tenant è
determinato dall'ID tenant). Il metodo getTenant()
verrà risolto con le versioni di base
informazioni sul tenant (come ID tenant, nome visualizzato e impostazioni del provider email),
ma per chiamare le API su quel tenant, devi usare
authForTenant(tenantFromGetTenant.tenantId)
.
Creazione di un tenant
Utilizza il metodo createTenant()
per creare una nuova configurazione del tenant:
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());
Puoi fornire qualsiasi combinazione di queste proprietà:
Proprietà | Tipo | Descrizione |
---|---|---|
displayName |
string |
Il nome visualizzato del tenant. Deve avere una lunghezza compresa tra 4 e 20 caratteri, costituiti da lettere, cifre e trattini e deve iniziare con una lettera. |
emailSignInConfig |
{ enable: boolean, passwordRequired: boolean } |
La configurazione del provider di accesso email. Ciò include se le email se il provider è abilitato e se è necessaria una password per accedere all'email. Quando non è richiesto, l'accesso via email può essere eseguito con la password o utilizzando accesso tramite email. |
multiFactorConfig |
{ state: 'DISABLED' | 'ENABLED', factorIds: string[] } |
Indica se
autenticazione a più fattori
sia abilitata per il tenant e i tipi di fattori consentiti. Attualmente,
l'unico ID fattore supportato è phone .
|
testPhoneNumbers |
{ string: string } |
Mappa dei numeri di telefono e autenticazione a più fattori associata
codici per la registrazione
scopi del test.
È consentito un massimo di 10 voci. Per rimuovere tutti i numeri di telefono di prova, imposta
questo campo a null .
|
Il metodo restituisce un oggetto Tenant
per il tenant appena creato.
Aggiornamento di un tenant
Utilizza il metodo updateTenant()
per modificare i dati di un tenant esistente. Ti serviranno
per specificare tenantId
, insieme alle proprietà da aggiornare per quel tenant.
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()
accetta le stesse proprietà di createTenant()
. Tutte le proprietà
sono facoltativi. Se non viene specificata una proprietà, il valore esistente non sarà
modificato.
Il metodo restituisce un oggetto Tenant
aggiornato al completamento. Se l'oggetto
tenantId
non appartiene a un tenant esistente, la promessa restituita viene rifiutata
con un errore auth/tenant-not-found
.
Eliminazione di un tenant
Puoi eliminare un tenant utilizzando il suo 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);
Il metodo restituisce un risultato vuoto quando l'eliminazione viene completata correttamente.
Se il valore tenantId
fornito non appartiene a un tenant esistente, il valore
la promessa viene rifiutata con un errore di auth/tenant-not-found
.
Elenco dei tenant
Utilizza il metodo listTenants()
per elencare i tenant esistenti:
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()); }
Ogni batch di risultati contiene un elenco di tenant, oltre a un token per la pagina successiva
per elencare il batch successivo di tenant. Quando tutti i tenant sono già stati elencati,
non viene restituito alcun pageToken
.
Se non viene specificato alcun campo maxResults
, il valore predefinito è 1000 tenant per batch.
Questo è anche il numero massimo di tenant che possono essere elencati alla volta.
Qualsiasi valore maggiore del massimo genererà un errore relativo all'argomento.
Se non viene specificato alcun pageToken
, il metodo elencherà i tenant del
partendo da zero.
Gestione programmatica dei provider SAML e OIDC
L'SDK Admin fornisce le API per la gestione del linguaggio di markup delle asserzioni di sicurezza. (SAML) 2.0 e le configurazioni del provider OpenID Connect (OIDC) in modo programmatico da un ambiente server protetto.
Con l'SDK Admin, puoi gestire questi provider per un tenant specifico. È simile a la gestione dei provider OIDC e SAML a livello di progetto.
Per gestire i provider per un tenant, crea prima un'istanza 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");
Puoi quindi eseguire operazioni comuni, come la creazione, Modifica o eliminazione dei provider per un tenant.
Creazione di un provider
Il codice seguente mostra come creare un provider SAML per un 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());
Modifica di un provider
Il seguente codice mostra come modificare un provider:
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());
Richiesta di un fornitore
Il codice seguente mostra come recuperare la configurazione del provider per un tenant specifico utilizzando l'ID provider:
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());
Fornitori di schede
Il codice seguente mostra come elencare le configurazioni del provider per un determinato 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()); }
Eliminazione di un provider
Il seguente codice mostra come eliminare un provider:
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");
I provider OIDC vengono gestiti in modo simile ai provider OIDC a livello di progetto, ad eccezione
possono essere gestite dall'istanza TenantAwareAuth
corrispondente,
rispetto a un'istanza a livello di progetto Auth
.
Per saperne di più, consulta: Gestione programmatica dei provider SAML e OIDC.
Gestione di utenti specifici dei tenant
Puoi utilizzare SDK Admin per creare, recuperare, aggiornare, eliminare ed elencare a tutti gli utenti per un tenant specifico.
Per iniziare, è necessaria un'istanza TenantAwareAuth
per il tenant corrispondente:
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");
Acquisizione di un utente
Puoi recuperare un utente specifico del tenant con un identificatore 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());
Puoi anche identificare un utente tramite il suo indirizzo email:
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());
Creazione di un utente
Utilizza il metodo createUser()
per creare nuovi utenti per un tenant specifico.
Quando crei un nuovo utente, fornire un uid
è facoltativo. se non specificato,
Identity Platform eseguirà il provisioning di un indirizzo univoco.
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());
Modifica di un utente
Puoi modificare gli utenti esistenti specificando il relativo uid
nel campo
Metodo 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());
Eliminare un utente
L'esempio seguente mostra come eliminare un utente in base ai suoi 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);
Utenti della scheda
Per recuperare un intero elenco di utenti per un tenant specifico in batch, utilizza
listUsers()
. Ogni batch conterrà un elenco di record utente, più un
pagina successiva se rimangono altri utenti.
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(); }
Consulta la documentazione di SDK Admin su gestione degli utenti per saperne di più.
Importazione degli utenti
Puoi utilizzare SDK Admin per importare gli utenti in blocco in un con privilegi elevati. Questo approccio offre numerosi vantaggi, ad esempio possibilità di eseguire la migrazione degli utenti da un altro prodotto Identity Platform, da un altro tenant o da un sistema di autenticazione esterno che utilizza di hashing. Puoi anche importare utenti con provider federati (come SAML e OIDC) e le rivendicazioni personalizzate direttamente in blocco.
Per iniziare, ottieni un'istanza TenantAwareAuth
per il tenant corrispondente:
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");
Puoi importare fino a 1000 utenti alla volta utilizzando un algoritmo di hashing specifico.
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()); }
L'elemento tenantId
di tutti gli utenti importati sarà impostato su tenantAuth.tenantId
.
Gli utenti senza password possono anche essere importati in un tenant specifico. Questi utenti possono essere importate con provider federati e attestazioni personalizzate.
Nodo,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()); }
Vedi Importare utenti nella consulta la documentazione su SDK Admin per saperne di più.
Verifica dell'identità
Quando un'app client di Identity Platform comunica con un backend personalizzato è necessario identificare l'utente che ha attualmente eseguito l'accesso. Questa operazione può essere eseguita in modo sicuro inviando il token ID dell'utente una volta completata l'operazione accedi tramite una connessione sicura al tuo server. Il server può quindi verificare l'integrità e l'autenticità del token ID.
L'SDK Admin dispone di un metodo integrato per la verifica e la decodifica dei token ID per di un tenant specifico.
Dopo aver eseguito correttamente l'accesso di un utente a un tenant specifico dal client, recupera il token ID dell'utente utilizzando l'SDK del client:
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.
});
Crea un'istanza TenantAwareAuth
sul 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");
Puoi quindi verificare il token ID per quel tenant specifico:
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
});
Una risorsa lato server potrebbe essere accessibile da più tenant con diverse diversi livelli di accesso. Poiché l'ID tenant potrebbe non essere noto in anticipo in questo in questo caso, il token ID può essere prima verificato a livello di progetto.
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()); }
Consulta la documentazione di SDK Admin su verificare i token ID per saperne di più.
Gestione delle sessioni utente
Le sessioni di Identity Platform hanno una lunga durata. Ogni volta che un utente accede, le credenziali dell'utente vengono verificate sul server di Identity Platform, scambiato con un token ID di breve durata e un token di aggiornamento di lunga durata. Un ID durano un'ora. I token di aggiornamento non scadono mai, tranne quando un utente Disattivazione, eliminazione o modifica di grande entità all'account (ad esempio, un indirizzo email o una password) aggiornamento).
In alcuni casi, potrebbe essere necessario revocare il token di aggiornamento di un utente per motivi di sicurezza motivi, come la segnalazione da parte dell'utente di un dispositivo smarrito o rubato, la scoperta di un una vulnerabilità generale all'interno di un'app o una perdita su larga scala di token attivi. SDK Admin fornisce un'API per revocare tutti i token di aggiornamento emessi per un un utente specificato di un tenant specifico.
Per iniziare, è necessaria un'istanza 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");
I token di aggiornamento possono quindi essere revocati specificando il uid
dell'utente:
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)");
Una volta revocati i token di aggiornamento, non è possibile emettere nuovi token ID per quell'utente fino a quando non avranno eseguito nuovamente l'autenticazione. Tuttavia, i token ID esistenti rimangono attivi fino alla scadenza naturale (un'ora).
Puoi verificare che un token ID valido non scaduto non sia stato revocato specificando
il parametro facoltativo checkRevoked
; questa funzionalità controlla se un token è stato revocato dopo
ne siano verificate l'integrità e l'autenticità.
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 } }
Consulta la documentazione di SDK Admin su gestione delle sessioni per saperne di più.
Controllo dell'accesso con rivendicazioni personalizzate
SDK Admin supporta la definizione di attributi personalizzati negli account utente per un un tenant specifico. Questi attributi consentono di implementare vari livelli di accesso e il controllo degli accessi, come controllo dell'accesso basato sui ruoli. Gli attributi possono essere utilizzata per assegnare agli utenti diversi livelli di accesso imposti dal regole di sicurezza.
Per iniziare, ottieni un'istanza TenantAwareAuth
per il tenant corrispondente:
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");
Le rivendicazioni personalizzate possono contenere dati sensibili, quindi devono essere impostate solo da un con privilegi usando SDK Admin.
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.
Gli attributi personalizzati appena impostati verranno visualizzati negli attributi di primo livello del token
payload non appena l'utente accede o aggiorna i propri token ID su un
sessione esistente. Nell'esempio precedente, il token ID contiene un token
rivendicazione: {admin: true}
.
Dopo aver verificato il token ID e decodificato il suo payload, lo strumento le rivendicazioni possono quindi essere controllate per applicare il controllo dell'accesso.
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. }
Le richieste personalizzate per un utente esistente per un tenant specifico sono disponibili anche come nel record dell'utente.
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"));
Consulta la documentazione di SDK Admin su Rivendicazioni personalizzate per saperne di più.
Generazione di link di azione email in corso...
Con gli SDK client di Identity Platform, puoi inviare agli utenti di un specifiche email dei tenant contenenti i link da utilizzare per reimpostare le password, la verifica dell'indirizzo e l'accesso basato su email. Queste email sono inviate da Google e hanno una possibilità di personalizzazione limitata.
Con SDK Admin, puoi generare questi link in modo programmatico all'interno del nell'ambito di un tenant specifico.
Per iniziare, ottieni un'istanza TenantAwareAuth
per il tenant corrispondente:
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");
L'esempio seguente mostra come generare un link per verificare l'indirizzo email di un utente per un tenant specificato:
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);
Meccanismi simili sono disponibili per generare la reimpostazione della password
i link di accesso basati su email. Tieni presente che quando generi un link di azione email in un
contesto tenant, l'ID tenant deve essere analizzato dal link e impostato sulla
client Auth
prima di poter applicare il codice.
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.
});
Vedi Link di azione via email nella documentazione di SDK Admin per saperne di più.
Messaggi di errore
Nella tabella seguente sono elencati i messaggi di errore più comuni che possono essere visualizzati.
Codice di errore | Descrizione e passaggi di risoluzione |
---|---|
auth/billing-not-enabled |
Questa funzione richiede l'abilitazione della fatturazione. |
auth/invalid-display-name |
Il campo displayName deve essere una stringa valida. |
auth/invalid-name |
Il nome della risorsa fornito non è valido. |
auth/invalid-page-token |
Il token di pagina deve essere una stringa valida non vuota. |
auth/invalid-project-id |
Progetto padre non valido. Il progetto padre no o non lo ha fatto abilitare la multitenancy. |
auth/invalid-tenant-id |
L'ID tenant deve essere una stringa valida non vuota. |
auth/mismatching-tenant-id |
L'ID tenant dell'utente non corrisponde all'ID tenant attuale
ID tenant TenantAwareAuth .
|
auth/missing-display-name |
Nella risorsa che viene creata o modificata manca un nome visualizzato valido. |
auth/insufficient-permission |
L'utente non dispone di autorizzazioni sufficienti per accedere alla risorsa richiesta o eseguire l'operazione specifica del tenant. |
auth/quota-exceeded |
La quota del progetto per l'operazione specificata è stata superata. |
auth/tenant-not-found |
Nessun tenant corrispondente all'identificatore fornito. |
auth/unsupported-tenant-operation |
Questa operazione non è supportata in un contesto multi-tenant. |
auth/invalid-testing-phone-number |
È stato fornito un numero di telefono di test o un codice di test non valido. |
auth/test-phone-number-limit-exceeded |
Il numero massimo consentito di coppie di numeri di telefono e codici di prova è stato superato. |