Crear controladores de acciones de correo electrónico personalizados

Algunas acciones de administración de usuarios, como actualizar la dirección de correo electrónico de un usuario y restablecer la contraseña de un usuario, dan como resultado que se envíen correos electrónicos al usuario. Estos correos electrónicos contienen enlaces que los destinatarios pueden abrir para completar o cancelar la acción de administración de usuarios. De forma predeterminada, los correos electrónicos de administración de usuarios se vinculan al controlador de acciones predeterminado, que es una página web alojada en una URL en el dominio de Firebase Hosting de su proyecto.

En su lugar, puede crear y alojar un controlador de acciones de correo electrónico personalizado para realizar un procesamiento personalizado e integrar el controlador de acciones de correo electrónico con su sitio web.

Las siguientes acciones de administración de usuarios requieren que el usuario complete la acción utilizando un controlador de acciones de correo electrónico:

  • Restablecer contraseñas
  • Revocar cambios en la dirección de correo electrónico: cuando los usuarios cambian las direcciones de correo electrónico principales de sus cuentas, Firebase envía un correo electrónico a sus direcciones anteriores que les permite deshacer el cambio.
  • Verificar direcciones de correo electrónico

Para personalizar el controlador de acciones de correo electrónico de tu proyecto de Firebase, debes crear y alojar una página web que utilice el SDK de JavaScript de Firebase para verificar la validez de la solicitud y completarla. Luego, debes personalizar las plantillas de correo electrónico de tu proyecto de Firebase para vincularlas a tu controlador de acciones personalizado.

Crear la página del controlador de acciones de correo electrónico

  1. Firebase agrega varios parámetros de consulta a la URL de su controlador de acciones cuando genera correos electrónicos de administración de usuarios. Por ejemplo:

    https://example.com/usermgmt?mode=resetPassword&oobCode=ABC123&apiKey=AIzaSy...&lang=fr

    Estos parámetros especifican la tarea de administración de usuarios que el usuario está completando. La página del controlador de acciones de correo electrónico debe manejar los siguientes parámetros de consulta:

    Parámetros
    modo

    La acción de gestión de usuarios que se va a completar. Puede ser uno de los siguientes valores:

    • resetPassword
    • recoverEmail
    • verifyEmail
    código oob Un código de un solo uso, utilizado para identificar y verificar una solicitud.
    Clave API La clave API de tu proyecto de Firebase, proporcionada para mayor comodidad
    continuar URL Esta es una URL opcional que proporciona una forma de devolver el estado a la aplicación a través de una URL. Esto es relevante para los modos de restablecimiento de contraseña y verificación de correo electrónico. Al enviar un correo electrónico de restablecimiento de contraseña o un correo electrónico de verificación, se debe especificar un objeto ActionCodeSettings con una URL de continuación para que esté disponible. Esto hace posible que un usuario continúe justo donde lo dejó después de una acción de correo electrónico.
    idioma

    Esta es la etiqueta de idioma BCP47 opcional que representa la configuración regional del usuario (por ejemplo, fr ). Puede utilizar este valor para proporcionar páginas de controlador de acciones de correo electrónico localizadas a sus usuarios.

    La localización se puede configurar a través de Firebase Console o dinámicamente llamando a la API del cliente correspondiente antes de activar la acción de correo electrónico. Por ejemplo, usando JavaScript: firebase.auth().languageCode = 'fr'; .

    Para una experiencia de usuario consistente, asegúrese de que la localización del controlador de acciones de correo electrónico coincida con la de la plantilla de correo electrónico.

    El siguiente ejemplo muestra cómo podría manejar los parámetros de consulta en un controlador basado en navegador. (También puede implementar el controlador como una aplicación Node.js usando una lógica similar).

    Web modular API

    import { initializeApp } from "firebase/app";
    import { getAuth } from "firebase/auth";
    
    document.addEventListener('DOMContentLoaded', () => {
      // TODO: Implement getParameterByName()
    
      // Get the action to complete.
      const mode = getParameterByName('mode');
      // Get the one-time code from the query parameter.
      const actionCode = getParameterByName('oobCode');
      // (Optional) Get the continue URL from the query parameter if available.
      const continueUrl = getParameterByName('continueUrl');
      // (Optional) Get the language code if available.
      const lang = getParameterByName('lang') || 'en';
    
      // Configure the Firebase SDK.
      // This is the minimum configuration required for the API to be used.
      const config = {
        'apiKey': "YOUR_API_KEY" // Copy this key from the web initialization
                                 // snippet found in the Firebase console.
      };
      const app = initializeApp(config);
      const auth = getAuth(app);
    
      // Handle the user management action.
      switch (mode) {
        case 'resetPassword':
          // Display reset password handler and UI.
          handleResetPassword(auth, actionCode, continueUrl, lang);
          break;
        case 'recoverEmail':
          // Display email recovery handler and UI.
          handleRecoverEmail(auth, actionCode, lang);
          break;
        case 'verifyEmail':
          // Display email verification handler and UI.
          handleVerifyEmail(auth, actionCode, continueUrl, lang);
          break;
        default:
          // Error: invalid mode.
      }
    }, false);

    Web namespaced API

    document.addEventListener('DOMContentLoaded', () => {
      // TODO: Implement getParameterByName()
    
      // Get the action to complete.
      var mode = getParameterByName('mode');
      // Get the one-time code from the query parameter.
      var actionCode = getParameterByName('oobCode');
      // (Optional) Get the continue URL from the query parameter if available.
      var continueUrl = getParameterByName('continueUrl');
      // (Optional) Get the language code if available.
      var lang = getParameterByName('lang') || 'en';
    
      // Configure the Firebase SDK.
      // This is the minimum configuration required for the API to be used.
      var config = {
        'apiKey': "YOU_API_KEY" // Copy this key from the web initialization
                                // snippet found in the Firebase console.
      };
      var app = firebase.initializeApp(config);
      var auth = app.auth();
    
      // Handle the user management action.
      switch (mode) {
        case 'resetPassword':
          // Display reset password handler and UI.
          handleResetPassword(auth, actionCode, continueUrl, lang);
          break;
        case 'recoverEmail':
          // Display email recovery handler and UI.
          handleRecoverEmail(auth, actionCode, lang);
          break;
        case 'verifyEmail':
          // Display email verification handler and UI.
          handleVerifyEmail(auth, actionCode, continueUrl, lang);
          break;
        default:
          // Error: invalid mode.
      }
    }, false);
  2. Maneje las solicitudes de restablecimiento de contraseña verificando primero el código de acción con verifyPasswordResetCode ; luego obtenga una nueva contraseña del usuario y pásela a confirmPasswordReset . Por ejemplo:

    Web modular API

    import { verifyPasswordResetCode, confirmPasswordReset } from "firebase/auth";
    
    function handleResetPassword(auth, actionCode, continueUrl, lang) {
      // Localize the UI to the selected language as determined by the lang
      // parameter.
    
      // Verify the password reset code is valid.
      verifyPasswordResetCode(auth, actionCode).then((email) => {
        const accountEmail = email;
    
        // TODO: Show the reset screen with the user's email and ask the user for
        // the new password.
        const newPassword = "...";
    
        // Save the new password.
        confirmPasswordReset(auth, actionCode, newPassword).then((resp) => {
          // Password reset has been confirmed and new password updated.
    
          // TODO: Display a link back to the app, or sign-in the user directly
          // if the page belongs to the same domain as the app:
          // auth.signInWithEmailAndPassword(accountEmail, newPassword);
    
          // TODO: If a continue URL is available, display a button which on
          // click redirects the user back to the app via continueUrl with
          // additional state determined from that URL's parameters.
        }).catch((error) => {
          // Error occurred during confirmation. The code might have expired or the
          // password is too weak.
        });
      }).catch((error) => {
        // Invalid or expired action code. Ask user to try to reset the password
        // again.
      });
    }

    Web namespaced API

    function handleResetPassword(auth, actionCode, continueUrl, lang) {
      // Localize the UI to the selected language as determined by the lang
      // parameter.
    
      // Verify the password reset code is valid.
      auth.verifyPasswordResetCode(actionCode).then((email) => {
        var accountEmail = email;
    
        // TODO: Show the reset screen with the user's email and ask the user for
        // the new password.
        var newPassword = "...";
    
        // Save the new password.
        auth.confirmPasswordReset(actionCode, newPassword).then((resp) => {
          // Password reset has been confirmed and new password updated.
    
          // TODO: Display a link back to the app, or sign-in the user directly
          // if the page belongs to the same domain as the app:
          // auth.signInWithEmailAndPassword(accountEmail, newPassword);
    
          // TODO: If a continue URL is available, display a button which on
          // click redirects the user back to the app via continueUrl with
          // additional state determined from that URL's parameters.
        }).catch((error) => {
          // Error occurred during confirmation. The code might have expired or the
          // password is too weak.
        });
      }).catch((error) => {
        // Invalid or expired action code. Ask user to try to reset the password
        // again.
      });
    }
  3. Maneje las revocaciones de cambios de direcciones de correo electrónico verificando primero el código de acción con checkActionCode ; luego restaure la dirección de correo electrónico del usuario con applyActionCode . Por ejemplo:

    Web modular API

    import { checkActionCode, applyActionCode, sendPasswordResetEmail } from "firebase/auth";
    
    function handleRecoverEmail(auth, actionCode, lang) {
      // Localize the UI to the selected language as determined by the lang
      // parameter.
      let restoredEmail = null;
      // Confirm the action code is valid.
      checkActionCode(auth, actionCode).then((info) => {
        // Get the restored email address.
        restoredEmail = info['data']['email'];
    
        // Revert to the old email.
        return applyActionCode(auth, actionCode);
      }).then(() => {
        // Account email reverted to restoredEmail
    
        // TODO: Display a confirmation message to the user.
    
        // You might also want to give the user the option to reset their password
        // in case the account was compromised:
        sendPasswordResetEmail(auth, restoredEmail).then(() => {
          // Password reset confirmation sent. Ask user to check their email.
        }).catch((error) => {
          // Error encountered while sending password reset code.
        });
      }).catch((error) => {
        // Invalid code.
      });
    }

    Web namespaced API

    function handleRecoverEmail(auth, actionCode, lang) {
      // Localize the UI to the selected language as determined by the lang
      // parameter.
      var restoredEmail = null;
      // Confirm the action code is valid.
      auth.checkActionCode(actionCode).then((info) => {
        // Get the restored email address.
        restoredEmail = info['data']['email'];
    
        // Revert to the old email.
        return auth.applyActionCode(actionCode);
      }).then(() => {
        // Account email reverted to restoredEmail
    
        // TODO: Display a confirmation message to the user.
    
        // You might also want to give the user the option to reset their password
        // in case the account was compromised:
        auth.sendPasswordResetEmail(restoredEmail).then(() => {
          // Password reset confirmation sent. Ask user to check their email.
        }).catch((error) => {
          // Error encountered while sending password reset code.
        });
      }).catch((error) => {
        // Invalid code.
      });
    }
  4. Maneje la verificación de la dirección de correo electrónico llamando a applyActionCode . Por ejemplo:

    Web modular API

    function handleVerifyEmail(auth, actionCode, continueUrl, lang) {
      // Localize the UI to the selected language as determined by the lang
      // parameter.
      // Try to apply the email verification code.
      applyActionCode(auth, actionCode).then((resp) => {
        // Email address has been verified.
    
        // TODO: Display a confirmation message to the user.
        // You could also provide the user with a link back to the app.
    
        // TODO: If a continue URL is available, display a button which on
        // click redirects the user back to the app via continueUrl with
        // additional state determined from that URL's parameters.
      }).catch((error) => {
        // Code is invalid or expired. Ask the user to verify their email address
        // again.
      });
    }

    Web namespaced API

    function handleVerifyEmail(auth, actionCode, continueUrl, lang) {
      // Localize the UI to the selected language as determined by the lang
      // parameter.
      // Try to apply the email verification code.
      auth.applyActionCode(actionCode).then((resp) => {
        // Email address has been verified.
    
        // TODO: Display a confirmation message to the user.
        // You could also provide the user with a link back to the app.
    
        // TODO: If a continue URL is available, display a button which on
        // click redirects the user back to the app via continueUrl with
        // additional state determined from that URL's parameters.
      }).catch((error) => {
        // Code is invalid or expired. Ask the user to verify their email address
        // again.
      });
    }
  5. Aloje la página en algún lugar, por ejemplo utilice Firebase Hosting .

A continuación, debe configurar su proyecto de Firebase para vincularlo a su controlador de acciones de correo electrónico personalizado en sus correos electrónicos de administración de usuarios.

Para configurar su proyecto de Firebase para usar su controlador de acciones de correo electrónico personalizado:

  1. Abra su proyecto en Firebase console .
  2. Vaya a la página Plantillas de correo electrónico en la sección Autenticación .
  3. En cualquiera de las entradas de Tipos de correo electrónico , haga clic en el icono de lápiz para editar la plantilla de correo electrónico.
  4. Haga clic en personalizar URL de acción y especifique la URL de su controlador de acciones de correo electrónico personalizado.

Después de guardar la URL, será utilizada por todas las plantillas de correo electrónico de su proyecto de Firebase.