Cette page a été traduite par l'API Cloud Translation.
Switch to English

S'authentifier avec une architecture mutualisée

Ce document explique comment authentifier les utilisateurs dans un environnement Identity Platform mutualisé.

Avant de commencer

Assurez-vous d'avoir activé l'architecture mutualisée pour votre projet et configuré vos locataires. Pour en savoir plus, consultez la page Premiers pas avec l'architecture mutualisée.

Vous devez également ajouter le SDK client à votre application :

  1. Accédez à la page "Identity Platform" dans Cloud Console.
    Accéder à la page des utilisateurs "Identity Platform"

  2. En haut à droite, cliquez sur Informations sur la configuration de l'application.

  3. Copiez le code dans votre application Web. Exemples :

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

Se connecter avec des locataires

Pour vous connecter à un locataire, l'ID de locataire doit être transmis à l'objet auth. Notez que tenantId n'est pas conservé lors de l'actualisation de la page.

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

Toute demande de connexion ultérieure depuis cette instance auth inclura l'ID de locataire (TENANT_ID1 dans l'exemple précédent) jusqu'à ce que vous modifiiez ou réinitialisiez l'ID de locataire.

Vous pouvez utiliser plusieurs locataires à l'aide d'une ou de plusieurs instances auth.

Pour utiliser une seule instance de auth, modifiez la propriété tenantId chaque fois que vous souhaitez basculer entre les locataires. Pour revenir aux fournisseurs d'identité au niveau du projet, définissez tenantId sur 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;

Pour utiliser plusieurs instances, créez une instance auth pour chaque locataire et attribuez aux instances des ID différents :

// 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';

Après la connexion avec un locataire, un utilisateur locataire est renvoyé avec l'option user.tenantId définie sur ce locataire. Notez que si vous basculez tenantId sur l'instance auth ultérieurement, la propriété currentUser ne sera pas modifiée. Elle pointera toujours vers le même utilisateur que le locataire précédent.

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

Comptes de messagerie/mot de passe

L'exemple suivant montre comment enregistrer un nouvel utilisateur :

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

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

Pour vous connecter à un utilisateur existant :

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

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

SAML

Pour vous connecter avec un fournisseur SAML, instanciez une instance SAMLAuthProvider avec l'ID de fournisseur dans Cloud Console :

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

Vous pouvez ensuite utiliser une fenêtre pop-up ou un flux de redirection pour vous connecter au fournisseur SAML.

L'exemple suivant illustre le flux de fenêtre pop-up :

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

Redirection

L'exemple suivant illustre le flux de redirection :

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

Dans les deux cas, veillez à définir l'ID de locataire approprié sur l'instance auth.

Pour lancer le flux d'authentification, affichez une interface invitant l'utilisateur à indiquer son adresse e-mail, puis appelez sendSignInLinkToEmail pour lui envoyer un lien d'authentification. Veillez à définir l'ID de locataire approprié sur l'instance auth avant d'envoyer l'e-mail.

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

Pour terminer la connexion sur la page de destination, analysez d'abord l'ID de locataire à partir du lien d'e-mail et définissez-le sur l'instance auth. Ensuite, appelez signInWithEmailLink avec l'adresse e-mail de l'utilisateur et le lien d'e-mail réel contenant le code à usage unique.

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

Créer des jetons personnalisés

La création d'un jeton personnalisé mutualisé est identique à la création d'un jeton personnalisé standard. Tant que l'ID de locataire approprié a été défini sur l'instance auth, une revendication tenant_id de premier niveau est ajoutée au JWT obtenu. Consultez la section Créer des jetons personnalisés pour obtenir des instructions détaillées sur la création et l'utilisation de jetons personnalisés.

L'exemple suivant montre comment créer un jeton personnalisé à l'aide du SDK 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);
  });

Le code suivant montre comment se connecter à l'aide d'un jeton personnalisé :

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

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

Notez que si les ID de locataire ne correspondent pas, la méthode signInWithCustomToken() échoue.

Associer des identifiants utilisateur mutualisés

Vous pouvez associer d'autres types d'identifiants à un utilisateur mutualisé existant. Par exemple, si un utilisateur s'est précédemment authentifié auprès d'un fournisseur SAML dans un locataire, vous pouvez ajouter une connexion par e-mail/mot de passe à son compte existant pour qu'il puisse utiliser l'une ou l'autre méthode de connexion au locataire.

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

Lorsque vous associez ou réauthentifiez un utilisateur mutualisé existant, auth.tenantId est ignoré. Utilisez user.tenantId pour spécifier le locataire à utiliser. Cela s'applique également aux autres API de gestion des utilisateurs, telles que updateProfile et updatePassword.

Gérer les erreurs de compte existant avec un identifiant différent

Si vous avez activé le paramètre Associer les comptes qui utilisent la même adresse e-mail dans Cloud Console, lorsqu'un utilisateur tente de se connecter à un fournisseur (tel que SAML) avec une adresse e-mail existant déjà pour un autre fournisseur (tel que Google), l'erreur auth/account-exists-with-different-credential est générée (avec un objet AuthCredential).

Pour terminer la connexion au fournisseur désiré, l'utilisateur doit d'abord se connecter au fournisseur existant (Google), puis l'associer à l'ancien AuthCredential (SAML).

Vous pouvez utiliser une fenêtre pop-up ou un flux de redirection pour gérer cette erreur.

L'exemple suivant montre comment gérer les erreurs auth/account-exists-with-different-credential lors de l'utilisation de 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();
                  });
              });
          }
        });
    }
  });

Redirection

Lorsque vous utilisez signInWithRedirect, des erreurs auth/account-exists-with-different-credential sont générées dans getRedirectResult à la fin du flux de redirection.

L'objet d'erreur contient la propriété error.tenantId. Comme l'ID de locataire sur l'instance auth n'est pas conservé après la redirection, vous devez définir l'ID de locataire de l'objet d'erreur sur l'instance auth.

L'exemple suivant montre comment gérer l'erreur :

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

Étape suivante