[Firebase] Authenticationでメール認証 (Web編) その3

第1回はメールアドレスとパスワードによる認証、第2回はメールアドレス宛にメールを送信し文中のURLをクリックするとログイン状態になる機能の実装に挑戦しました。

今回は次のような仕組みに挑戦してみます。

  1. メールアドレスとパスワードを入力しログイン
  2. ログイン後、メールアドレスの認証が終わってなければ確認メール送信
  3. 確認メール内にあるURLをクリックするとメールアドレスの認証完了 [:contents]

メールアドレスの確認

コンソールの設定

第1回で行った、以下の設定が必要です。「Authentication」から「ログイン方法」タブに移動し「メール/パスワード」を有効にしてください。

JSで認証処理

/js/config.js

共通処理を書いておくJSです。 第2回と全く同じです。

//----------------------------------------------
// Firebaseの初期化
//----------------------------------------------
// コンソールの内容をそのままコピペ
var config = {
  apiKey: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
  authDomain: "test-f76bc.firebaseapp.com",
  databaseURL: "https://test-f76bc.firebaseio.com",
  projectId: "test-f76bc",
  storageBucket: "test-f76bc.appspot.com",
  messagingSenderId: "00000000000"
};
firebase.initializeApp(config);

//----------------------------------------------
// ドメインとポート番号
//----------------------------------------------
let domain = document.domain;
let port   = (domain === 'localhost')?  5000:80;

/auth/mail2/index.html

ユーザーが最初にアクセスするログイン画面です。 こちらは第1回で使用した設定用JSONに戻しました。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Hello Firebase Auth</title>
  <link type="text/css" rel="stylesheet" href="https://cdn.firebase.com/libs/firebaseui/3.5.2/firebaseui.css" />
  <style>h1{text-align: center;}</style>
</head>
<body>
  <h1>Hello Firebase Auth</h1>
  <div id="firebaseui-auth-container"></div>

  <script src="https://www.gstatic.com/firebasejs/5.8.1/firebase-app.js"></script>
  <script src="https://www.gstatic.com/firebasejs/5.8.1/firebase-auth.js"></script>
  <script src="https://www.gstatic.com/firebasejs/ui/3.5.2/firebase-ui-auth__ja.js"></script>
  <script src="/js/config.js"></script>
  <script>
    //----------------------------------------------
    // Firebase UIの設定
    //----------------------------------------------
    var uiConfig = {
        // ログイン完了時のリダイレクト先
        signInSuccessUrl: '/auth/mail2/done.html',

        // 利用する認証機能
        signInOptions: [
          firebase.auth.EmailAuthProvider.PROVIDER_ID  //メール認証
        ],

        // 利用規約のURL(任意で設定)
        tosUrl: 'http://example.com/kiyaku/',
        // プライバシーポリシーのURL(任意で設定)
        privacyPolicyUrl: 'http://example.com/privacy'
      };

      var ui = new firebaseui.auth.AuthUI(firebase.auth());
      ui.start('#firebaseui-auth-container', uiConfig);
  </script>
</body>
</html>

/auth/mail2/done.html

今回の話のメインはこちらですね。 ログイン時に渡されるオブジェクトのuser.emailVerifiedfalseであればまだメールアドレスの確認が行われていないことになります。その場合にuser.sendEmailVerification()メソッドを使用し、メールアドレス宛に確認メールを送信しています。

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <title>Hello Firebase Auth</title>
</head>
<body>
  <h1>...Please wait</h1>
  <div id="info"></div>

  <script src="https://www.gstatic.com/firebasejs/5.8.1/firebase-app.js"></script>
  <script src="https://www.gstatic.com/firebasejs/5.8.1/firebase-auth.js"></script>
  <script src="/js/config.js"></script>
  <script>
    firebase.auth().onAuthStateChanged( (user) => {
      console.log(user);

      //------------------------------------
      // 未ログイン状態で訪れた場合
      //------------------------------------
      if(user === null){
        showMessage('Not Login', 'ログインが必要な画面です');
        return(false);
      }

      //------------------------------------
      // メアド確認済み
      //------------------------------------
      if( user.emailVerified ) {
        showMessage('Login Complete!', `${user.displayName}さんがログインしました`);
      }
      //------------------------------------
      // メアド未確認
      //------------------------------------
      else {
        user.sendEmailVerification()
          .then(()=>{
            showMessage('Send confirm mail', `${user.email}宛に確認メールを送信しました`);
          })
          .catch((error)=>{
            showMessage('[Error] Can not send mail', `${user.email}宛に確認メールを送信できませんでした: ${error}`);
          });
      }
    });

    function showMessage(title, msg) {
      document.querySelector('h1').innerText    = title;
      document.querySelector('#info').innerHTML = msg;
    }
  </script>
</body>
</html>

実行結果

クリックするとサンプルコードが実行できます。お試し登録やログインなどどうぞ。自分以外のメアドを入れたり悪いことしないでくださいね。(登録された内容は適当なタイミングで削除します) test-f76bc.firebaseapp.com

done.htmlで送信されたメール内のURLをクリックすると、デフォルトで用意されているメールアドレスの確認ページが表示され、user.emailVerifiedの値がそれ以降trueに変化します。もう一度ログインを行うと今度は確認メールが送信されず、ログインが完了した旨が表示されれば成功です。

その他

メールの文面を変更する

デフォルトの確認メールの文面は中々怪しさに溢れているので、Web画面の開発が一段落したらこちらの文面も差し替えた方が良いでしょう。

コンソールの「Authentication」から「テンプレート」タブにアクセスするとカスタマイズができます。

確認ページから遷移させる

メール内のURLをクリックすると以下のような簡単な画面が表示されます。 これだけだと次のアクションをどうすればよいかユーザーが混乱しますので、実際には次のページへ遷移するためのボタンなどを置いた方がユーザーフレンドリーです。

というわけで、done.htmlのコードを修正しました。 sendEmailVerification()に引数として設定用のJSONを渡しています。変数domainportの値はconfig.jsで作成しています。

  actionCodeSettings = {
    url: `http://${domain}:${port}/auth/mail2/done.html`
  };
  user.sendEmailVerification(actionCodeSettings)

このコードを実行すると、今度は以下のように「続行」ボタンが表示されましたね。

なおここで指定するURLのドメインはホワイトリストに登録されている必要があるのでご注意を。 コンソールにログインしたら「Authentication」内の「ログイン方法」タブをクリックし「承認済みドメイン」の項目の右側にある「ドメインの追加」ボタンから設定します。

参考ページ

firebase.google.com firebase.google.com