カスタムのメール アクション ハンドラの作成

メールアドレスの更新やユーザー パスワードのリセットなど、一部のユーザー管理操作では、ユーザーにメールが送信されます。これらのメールには、そのユーザー管理操作を完了またはキャンセルするためのリンクが含まれます。ユーザー管理のメールはデフォルトで、プロジェクトの Firebase Hosting ドメインの URL でホストされているウェブページである、アクション ハンドラにリンクします。

デフォルトのアクション ハンドラの代わりに、カスタム処理を行うアクション ハンドラを自分のウェブサイトに統合するために、メール アクション ハンドラを自作してホストすることもできます。

次のユーザー管理操作では、ユーザーがメールのアクション ハンドラを使用してアクションを完了する必要があります。

  • パスワードのリセット
  • メールアドレスの変更の取り消し - ユーザーが自分のアカウントのメインのメールアドレスを変更すると、その変更を元に戻せるよう、元のアドレスにメールが送信されます。
  • メールアドレスの確認

Firebase プロジェクトのメール アクション ハンドラをカスタマイズするには、リクエストの妥当性を検証し、リクエストを完了するウェブページを Firebase JavaScript SDK で作成しホストする必要があります。その後、Firebase プロジェクトのメール テンプレートをカスタマイズして、カスタム アクション ハンドラにリンクする必要があります。

メール アクション ハンドラのページを作成する

  1. Firebase はユーザー管理のメールを生成する際、アクション ハンドラの URL にいくつかのクエリ パラメータを追加します。次に例を示します。

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

    これらのパラメータは、完了しようとしているユーザー管理タスクを指定しています。メール アクション ハンドラのページでは、次のクエリ パラメータを処理する必要があります。

    パラメータ
    mode

    完了するユーザー管理操作。次のいずれかの値です。

    • resetPassword
    • recoverEmail
    • verifyEmail
    oobCode リクエストを識別し、検証するためのワンタイム コード
    apiKey 利便性のために提供される Firebase プロジェクトの API キー
    continueUrl URL を使用して状態をアプリに戻す方法を提供するオプションの URL。これは、パスワード リセットとメール確認モードに関係します。パスワード リセットのメールまたは確認メールを送信するときは、ActionCodeSettings オブジェクトを続行 URL で指定して、このパラメータを使用できるようにする必要があります。これにより、ユーザーはメール アクション後に中断したところから続行できます。
    lang

    ユーザーのロケールを表す省略可能な BCP47 言語タグです(例: fr)。この値を使用して、ローカライズされたメールのアクション ハンドラのページをユーザーに提供できます。

    Firebase コンソールを使用してローカライズを設定できます。また、メール アクションをトリガーする前に対応するクライアント API を呼び出すことによって、動的にローカライズを設定することもできます。たとえば、JavaScript では次のように使用します。firebase.auth().languageCode = 'fr';

    一貫したユーザー エクスペリエンスのために、メールのアクション ハンドラのローカライズが、メール テンプレートのものと一致することを確認してください。

    次の例は、ブラウザベースのハンドラ内でクエリ パラメータを処理する方法を示しています(また、同様のロジックを使用して Node.js アプリケーションとしてハンドラを実装できます)。

    ウェブ モジュラー 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': "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

    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. 最初に verifyPasswordResetCode でアクション コードを確認することによって、パスワードの再設定リクエストを処理し、その後ユーザーから新しいパスワードを取得して、それを confirmPasswordReset に渡します。次に例を示します。

    ウェブ向けのモジュラー 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.
      });
    }

    名前空間が指定されたウェブ 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. 最初に checkActionCode でアクション コードを検証することによって、メールアドレスの変更取消しを処理し、その後、applyActionCode でユーザーのメールアドレスを復元します。次に例を示します。

    ウェブ向けのモジュラー 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.
      });
    }

    名前空間が指定されたウェブ 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. applyActionCode の呼び出しで、メールアドレスの確認を処理します。次に例を示します。

    ウェブ向けのモジュラー 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.
      });
    }

    名前空間が指定されたウェブ 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. Firebase Hosting を使用するなどして、任意の場所でページをホストします。

次に、ユーザー管理メールでカスタムのメール アクション ハンドラにリンクするよう、Firebase プロジェクトを構成する必要があります。

カスタムのメール アクション ハンドラを使用するように、Firebase プロジェクトを構成するには:

  1. Firebase コンソールでプロジェクトを開きます。
  2. [Authentication] セクションで [Templates] ページに移動します。
  3. [メールの種類] エントリで、メールのテンプレートを編集するために鉛筆アイコンをクリックします。
  4. [アクション URL をカスタマイズ] をクリックして、カスタムのメール アクション ハンドラの URL を指定します。

URL は、保存した後、Firebase プロジェクトのすべてのメール テンプレートで使用されます。