Crea controladores de acciones de correo electrónico personalizados

Algunas acciones de administración de usuarios, como actualizar la dirección de correo electrónico o restablecer la contraseña, conllevan el envío de correos electrónicos al usuario. Estos correos electrónicos contienen vínculos que los destinatarios pueden abrir para completar o cancelar la acción. Según la configuración predeterminada, los correos electrónicos de administración de usuarios vinculan al controlador predeterminado de la acción, que corresponde a una página web alojada en una URL en el dominio de Firebase Hosting de tu proyecto.

En lugar de eso, puedes crear y alojar un controlador de acciones de correo electrónico personalizado para integrarlo en tu sitio web y hacer un procesamiento personalizado.

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

  • Restablecer contraseñas
  • Revocar cambios de la dirección de correo electrónico (cuando un usuario cambia la dirección de correo electrónico principal de su cuenta, Firebase envía un correo electrónico a la dirección antigua, que le permite deshacer el cambio)
  • Verificar direcciones de correo electrónico

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

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

  1. Firebase agrega varios parámetros de consulta a la URL del 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 está completando el usuario. Tu página del controlador de acciones de correo electrónico debe administrar los siguientes parámetros de búsqueda:

    Parámetros
    mode

    La acción de administración de usuarios que se completará. Puede tener uno de los siguientes valores:

    • resetPassword
    • recoverEmail
    • verifyEmail
    oobCode Un código que se usa por única vez para identificar y verificar una solicitud.
    apiKey La clave de API del proyecto de Firebase, que se proporciona para tu comodidad.
    continueUrl Esta es una URL opcional que proporciona una manera de pasar el estado a la app mediante una URL. Esto se aplica para los modos de verificación de correo electrónico y de restablecimiento de contraseña. Cuando envías un correo electrónico de restablecimiento de contraseña o uno de verificación, se debe especificar un objeto ActionCodeSettings con una URL de continuación para que esta función esté disponible. Esto hace posible que un usuario continúe desde donde abandonó después de una acción de correo electrónico.
    lang

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

    La localización se puede configurar mediante Firebase console o de forma dinámica si se llama a la API del cliente en cuestión antes de activar la acción de correo electrónico. Por ejemplo, mediante JavaScript: firebase.auth().languageCode = 'fr';.

    Para que la experiencia del usuario sea coherente, asegúrate de que la localización del controlador de la acción de correo electrónico coincida con las plantillas del correo electrónico.

    El siguiente ejemplo muestra cómo podrías administrar los parámetros de consulta en un controlador basado en el navegador. También puedes implementar el controlador como una aplicación de Node.js con una lógica similar.

    API modular web

    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': "YOU_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);

    API con espacio de nombres web

    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. Para controlar solicitudes de restablecimiento de contraseña, verifica el código de acción con verifyPasswordResetCode y, luego, obtén una nueva contraseña del usuario y pásala a confirmPasswordReset. Por ejemplo:

    API modular web

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

    API con espacio de nombres web

    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. Para controlar revocaciones de cambio de dirección de correo electrónico, verifica el código de acción con checkActionCode y, luego, restablece la dirección de correo electrónico del usuario con applyActionCode. Por ejemplo:

    API modular web

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

    API con espacio de nombres web

    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. Para controlar la verificación de direcciones de correo electrónico, llama a applyActionCode. Por ejemplo:

    API modular web

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

    API con espacio de nombres web

    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. Aloja la página en algún sitio; por ejemplo, usa Firebase Hosting.

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

Si deseas configurar el proyecto de Firebase para que use el controlador de acciones de correo electrónico personalizado, sigue estos pasos:

  1. Abre el proyecto en Firebase console.
  2. Ve a la página Plantillas de correo electrónico en la sección Auth.
  3. En cualquiera de las entradas de Tipos de correo electrónico, haz clic en el ícono de lápiz para editar la plantilla de correo electrónico.
  4. Haz clic en personalizar URL de acción y especifica la URL al controlador de acciones de correo electrónico personalizado.

Después de que guardes la URL, la usarán todas las plantillas de correo electrónico del proyecto de Firebase.