Se usó la API de Cloud Translation para traducir esta página.
Switch to English

Autentica con grupos de usuarios multiples

En este documento, se muestra cómo autenticar usuarios en un entorno de varios usuarios de Identity Platform.

Antes de comenzar

Asegúrate de haber habilitado los grupos de usuarios múltiples para tu proyecto y haber configurado tus grupos de usuarios. Consulta Comienza a usar grupos de usuarios múltiples para obtener información sobre cómo comenzar.

También deberás agregar el SDK cliente a tu app:

  1. Ve a la página de Identity Platform en Cloud Console.
    Ir a la página de usuarios de Identity Platform

  2. En la parte superior derecha, haz clic en detalles de la configuración de la aplicación.

  3. Copia el código a tu aplicación web. Por ejemplo:

    <script src="https://www.gstatic.com/firebasejs/x.x.x/firebase.js"></script>
    <script>
    // Initialize Identity Platform
    const config = {
      apiKey: "...",
      authDomain: "my-app-12345.firebaseapp.com"
    };
    firebase.initializeApp(config);
    </script>
    

Accede con los grupos de usuarios

Para acceder a una instancia, el ID de la instancia debe pasarse al objeto auth. Ten en cuenta que tenantId no se conserva cuando se vuelve a cargar la página.

var tenantId = TENANT_ID1;
firebase.auth().tenantId = tenantId;

Cualquier solicitud de acceso futura de esta instancia auth incluirá el ID del grupo (TENANT_ID1 en el ejemplo anterior) hasta que cambies o restablezcas el ID del grupo.

Puedes trabajar con grupos de usuario múltiples mediante una o varias instancias de auth.

Para usar una sola instancia de auth, modifica la propiedad tenantId cada vez que quieras cambiar entre usuarios. Para volver a los IdP a nivel de proyecto, establece tenantId en null:

// One Auth instance
// Switch to tenant1
firebase.auth().tenantId = 'tenant1';
// Switch to tenant2
firebase.auth().tenantId = 'tenant2';
// Switch back to project level IdPs
firebase.auth().tenantId = null;

A fin de usar grupos de usuarios múltiples, crea una nueva instancia auth para cada grupo de usuarios y asígnales ID diferentes:

// Multiple Auth instances
firebase.initializeApp(config, 'app1_for_tenantId1');
firebase.initializeApp(config, 'app2_for_tenantId2');

const auth1 = firebase.app('app1').auth();
const auth2 = firebase.app('app2').auth();

auth1.tenantId = 'tenant1';
auth2.tenantId = 'tenant2';

Después de acceder con un grupo de usuarios, un usuario del grupo de usuarios se mostrará con user.tenantId establecido en ese grupo. Ten en cuenta que si cambias tenantId en la instancia auth más adelante, la propiedad currentUser no cambiará, sino que apuntará al mismo usuario que el grupo de usuarios anterior.

// Switch to TENANT_ID1
firebase.auth().tenantId = 'TENANT_ID1';

// Sign in with tenant
firebase.auth().signInWithEmailAndPassword(email, password)
  .then((result) => {
    const user = result.user;
    // user.tenantId is set to 'TENANT_ID1'.
    // Switch to 'TENANT_ID2'.
    firebase.auth().tenantId = 'TENANT_ID2';
    // firebase.auth().currentUser still point to the user.
    // firebase.auth().currentUser.tenantId is 'TENANT_ID1'.
  });

// You could also get the current user from Auth state observer.
firebase.auth().onAuthStateChanged((user) => {
  if (user) {
    // User is signed in.
    // user.tenantId is set to 'TENANT_ID1'.
  } else {
    // No user is signed in.
  }
});

Cuentas de correo electrónico y contraseña

En el siguiente ejemplo, se muestra cómo registrar un usuario nuevo:

firebase.auth().tenantId = 'TENANT_ID';

firebase.auth().createUserWithEmailAndPassword(email, password)
  .then((result) => {
    // result.user.tenantId is 'TENANT_ID'.
  }).catch((error) => {
    // Handle error.
  });

Para acceder a un usuario existente, haz lo siguiente:

firebase.auth().tenantId = 'TENANT_ID';

firebase.auth().signInWithEmailAndPassword(email, password)
  .then((result) => {
    // result.user.tenantId is 'TENANT_ID'.
  }).catch((error) => {
    // Handle error.
  });

SAML

Para acceder con un proveedor de SAML, crea una instancia SAMLAuthProvider con el ID de proveedor de Cloud Console:

const provider = new firebase.auth.SAMLAuthProvider('saml.myProvider');

Luego, puedes usar una ventana emergente o un flujo de redireccionamiento para acceder al proveedor de SAML.

En el siguiente ejemplo, se muestra la ventana emergente:

// Switch to TENANT_ID1.
firebase.auth().tenantId = 'TENANT_ID1';

//Sign-in with popup.
firebase.auth().signInWithPopup(provider)
  .then((result) => {
    // User is signed in.
    // tenant ID is available in result.user.tenantId.
    // Identity provider data is available in result.additionalUserInfo.profile.
  })
  .catch((error) => {
    // Handle error.
  });

Redirect

En el siguiente ejemplo, se muestra el flujo de redireccionamiento:

// Switch to TENANT_ID1.
firebase.auth().tenantId = 'TENANT_ID1';

// Sign-in with redirect.
firebase.auth().signInWithRedirect(provider);

// After the user completes sign-in and returns to the app, you can get
// the sign-in result by calling getRedirectResult. However, if they sign out
// and sign in again with an IdP, no tenant is used.
firebase.auth().getRedirectResult()
  .then((result) => {
    // User is signed in.
    // The tenant ID available in result.user.tenantId.
    // Identity provider data is available in result.additionalUserInfo.profile.
  })
  .catch((error) => {
    // Handle error.
  });

En ambos casos, asegúrate de configurar el ID de grupo de usuarios correcto en la instancia auth.

A fin de iniciar el flujo de autenticación, muestra una interfaz que le pida al usuario proporcionar su dirección de correo electrónico y, luego, llama a sendSignInLinkToEmail para enviarle un vínculo de autenticación. Asegúrate de configurar el ID de usuario correcto en la instancia auth antes de enviar el correo electrónico.

// Switch to TENANT_ID1
firebase.auth().tenantId = 'TENANT_ID1';

firebase.auth().sendSignInLinkToEmail(email, actionCodeSettings)
  .then(function() {
    // The link was successfully sent. Inform the user.
    // Save the email locally so you don't need to ask the user for it again
    // if they open the link on the same device.
    window.localStorage.setItem('emailForSignIn', email);
  })
  .catch(function(error) {
    // Some error occurred, you can inspect the code: error.code
  });

Para completar el acceso en la página de destino, primero analiza el ID de usuario desde el vínculo de correo electrónico y configúralo en la instancia auth. Luego, llama a signInWithEmailLink con el correo electrónico del usuario y el vínculo de correo electrónico correspondiente que contiene el código único.

if (firebase.auth().isSignInWithEmailLink(window.location.href)) {
  const actionCodeUrl = firebase.auth.ActionCodeURL.parseLink(window.location.href);
  if (actionCodeUrl.tenantId) {
      firebase.auth().tenantId = actionCodeUrl.tenantId;
  }
  let email = window.localStorage.getItem('emailForSignIn');
  if (!email) {
    // User opened the link on a different device. To prevent session fixation
    // attacks, ask the user to provide the associated email again. For example:
    email = window.prompt('Please provide your email for confirmation');
  }
  firebase.auth().signInWithEmailLink(email, window.location.href)
    .then((result) => {
      // User is signed in.
      // tenant ID available in result.user.tenantId.
    });
}

Crear tokens personalizados

Crear un token personalizado con reconocimiento de múltiples instancias es idéntico a crear un token personalizado normal. Siempre que se establezca el ID de instancia correcto en la instancia auth, se agregará una reclamación tenant_id de nivel superior al JWT resultante. Consulta Crea tokens personalizados para obtener instrucciones detalladas sobre cómo crear y usar tokens personalizados.

En el siguiente ejemplo, se muestra cómo crear un token personalizado con el SDK de Admin:

// Ensure you're using a tenant-aware auth instance
const tenantManager = admin.auth().tenantManager();
const tenantAuth = tenantManager.authForTenant('TENANT_ID1');

// Create a custom token in the usual manner
tenantAuth.createCustomToken(uid)
  .then((customToken) => {
    // Send token back to client
  })
  .catch((error) => {
    console.log('Error creating custom token:', error);
  });

En el siguiente código, se demuestra cómo acceder con un token personalizado:

firebase.auth().tenantId = 'TENANT_ID1';

firebase.auth().signInWithCustomToken(token)
  .catch((error) => {
    // Handle Errors here.
    var errorCode = error.code;
    var errorMessage = error.message;
    // ...
  });

Ten en cuenta que si los ID de grupo de usuarios no coinciden, el método signInWithCustomToken() fallará.

Vincula credenciales de usuario de grupos de usuarios múltiples

Puedes vincular otros tipos de credenciales a un usuario de grupos de usuarios múltiples. Por ejemplo, si un usuario ya se autenticó con un proveedor de SAML en un grupo de usuarios, puedes agregar el acceso de correo electrónico/contraseña a su cuenta existente para que pueda usar cualquiera de los métodos para acceder a la instancia.

// Switch to TENANT_ID1
firebase.auth().tenantId = 'TENANT_ID1';

//Sign-in with popup
firebase.auth().signInWithPopup(provider)
  .then((result) => {
    // Existing user with SAML provider.
    const user = result.user;
    const emailCredential =
        firebase.auth.EmailAuthProvider.credential(email, password);
    return user.linkWithCredential(emailCredential);
  })
  .then((linkResult) => {
    // The user can sign in with both SAML and email/password now.
  });

Cuando se vincula o se vuelve a autenticar un usuario de instancias múltiples existente, se ignora auth.tenantId. usa user.tenantId para especificar qué instancia usar. Esto también se aplica a otras API de administración de usuarios, como updateProfile y updatePassword.

Maneja errores de cuentas que ya existen con otras credenciales

Si habilitaste la configuración Cuentas vinculadas que usan el mismo correo electrónico en Cloud Console, cuando un usuario intenta acceder a un proveedor (como SAML) con un correo electrónico que ya existe para otro proveedor (como Google), se muestra el error auth/account-exists-with-different-credential (junto con un objeto AuthCredential).

Para finalizar el acceso con el proveedor deseado, el usuario primero debe acceder al proveedor existente (Google) y, luego, establecer el vínculo con la AuthCredential (SAML) anterior.

Para controlar este error, puedes usar una ventana emergente o redireccionar el flujo.

En el siguiente ejemplo, se muestra cómo controlar los errores auth/account-exists-with-different-credential cuando se usa signInWithPopup:

// Step 1.
// User tries to sign in to the SAML provider in that tenant.
firebase.auth().tenantId = 'TENANT_ID';
firebase.auth().signInWithPopup(samlProvider)
  .catch((error) => {
    // An error happened.
    if (error.code === 'auth/account-exists-with-different-credential') {
      // Step 2.
      // User's email already exists.
      // The pending SAML credential.
      var pendingCred = error.credential;
      // The credential's tenantId if needed: error.tenantId
      // The provider account's email address.
      var email = error.email;
      // Get sign-in methods for this email.
      firebase.auth().fetchSignInMethodsForEmail(email)
        .then((methods) => {
          // Step 3.
          // Ask the user to sign in with existing Google account.
          if (methods[0] == 'google.com') {
            firebase.auth().signInWithPopup(googleProvider)
              .then((result) => {
                // Step 4
                // Link the SAML AuthCredential to the existing user.
                result.user.linkWithCredential(pendingCred)
                  .then(function(linkResult) {
                    // SAML account successfully linked to the existing
                    // user.
                    goToApp();
                  });
              });
          }
        });
    }
  });

Redirect

Cuando uses signInWithRedirect, los errores auth/account-exists-with-different-credential se generarán en getRedirectResult cuando finalices el flujo de redireccionamiento.

El objeto de error contiene la propiedad error.tenantId. Como el ID de instancia en la instancia auth no se conserva después del redireccionamiento, necesitarás configurar el ID de instancia del objeto de error a la instancia auth.

En el siguiente ejemplo, se muestra cómo controlar el error:

// Step 1.
// User tries to sign in to SAML provider.
firebase.auth().tenantId = 'TENANT_ID';
firebase.auth().signInWithRedirect(samlProvider);
// Redirect back from SAML IDP. auth.tenantId is null after redirecting.
firebase.auth().getRedirectResult().catch((error) => {
  if (error.code === 'auth/account-exists-with-different-credential') {
    // Step 2.
    // User's email already exists.
    var tenantId = error.tenantId;
    // The pending SAML credential.
    var pendingCred = error.credential;
    // The provider account's email address.
    var email = error.email;
    // Need to set the tenant ID again as the page was reloaded and the
    // previous setting was reset.
    firebase.auth().tenantId = tenantId;
    // Get sign-in methods for this email.
    firebase.auth().fetchSignInMethodsForEmail(email)
      .then((methods) => {
        // Step 3.
        // Ask the user to sign in with existing Google account.
        if (methods[0] == 'google.com') {
          firebase.auth().signInWithRedirect(googleProvider);
        }
      });
  }
});

// Redirect back from Google. auth.tenantId is null after redirecting.
firebase.auth().getRedirectResult().then((result) => {
  // Step 4
  // Link the SAML AuthCredential to the existing user.
  // result.user.tenantId is 'TENANT_ID'.
  result.user.linkWithCredential(pendingCred)
    .then(function(linkResult) {
      // SAML account successfully linked to the existing
      // user.
      goToApp();
    });
});

¿Qué sigue?