LoginSignup
113
86

More than 1 year has passed since last update.

Firebase Authentication を利用した認証システムの実装

Last updated at Posted at 2020-07-23

2022年2月追記

Firebase SDK v9では、実装方法が大きく変わりました。
v9を利用した認証の実装については、以下をご覧ください。

Authenticationを利用した実装

前回 に続き、 Firebase の備忘録を書いていきます。
今回はFirebase Authenticationを利用した認証システムの実装についてメモを残しておきます。

Firebase Authentication の設定

認証は、Firebase プロジェクトのコンソールから「Auhentication」を選んで設定していきます。

公式ドキュメントは以下。

ここでは、サンプルアプリで利用したGoogle 認証に絞って記述します。

Google 認証の設定

Authentication → Sign-in methodを選び、設定を「有効」に変更→保存で、終了。

Google認証の実装

Firebase SDKを利用します。

前項で書いた通り、認証用のSDKと構成オブジェクトのロードを済ませておきます。

  <script src="/__/firebase/7.16.0/firebase-app.js"></script> 
  <script src="/__/firebase/7.16.0/firebase-auth.js"></script> 
  <script src="/__/firebase/init.js"></script> 

実装方法は大まかに言うと

・Firebase UIの利用
・自前開発

の2つを選べます。

Firebase UIの利用

公式ドキュメントは こちら

基本的な流れは

・Firebase UI用のJSファイルとCSSファイルをロード
・Firebase UIをウェブアプリ内で初期化
・ウェブアプリ内のDOMに表示

となります。

詳しい流れは公式ドキュメントの通りでOK。
https://firebase.google.com/docs/auth/web/firebaseui#before_you_begin

最初に、Firebase UI用のJSファイルとCSSファイルをロードします。ライブラリはhead要素内で読み込むように指定するようです。

<head>
  <title>Firebase Authentication sample 01</title>
  <script src="https://cdn.firebase.com/libs/firebaseui/3.5.2/firebaseui.js"></script>
  <link href="https://cdn.firebase.com/libs/firebaseui/3.5.2/firebaseui.css" rel="stylesheet" type="text/css">
</head>

初期化

Googleを利用する場合の初期化は以下に記述されています。

サンプルコードではGoogle以外に、FacebookやTwitterなど、別な認証用の記述があります。今回のサンプルの様に、Googleによる認証のみ行う場合、他の手段は削除してOK。

サンプルコードでは「#firebaseui-auth-container」と言うIDのDOMを指定しているが、DOMの指定はなんでも良い。

ログインチェック

onAuthStateChangedメソッドを使います。
https://firebase.google.com/docs/auth/web/start#set_an_authentication_state_observer_and_get_user_data

サインアウト

サインアウトメソッドを実行するだけです。簡単。


firebase.auth().signOut().then(function() {
  // Sign-out successful.
}).catch(function(error) {
  // An error happened.
});

サンプルコード

これらを踏まえて、サンプルコードを実装してみました。仕様は以下の通り。

  • Google を利用して認証する
  • Firebase Authentication UIを利用して実装。
  • 初期画面では、Googleのサインインボタンを表示
  • サインインすると、Google ユーザーのユーザー名をウェルカムメッセージとともに表示する。
  • サインアウト すると、Authentication UIの初期画面に戻る。

実際に動くサンプルは こちら で公開しています。
https://todomanage.web.app/sample/auth-sample01.html

サンプルコード
auth-sample01.html

<!DOCTYPE html>
<html lang="ja">
<head>
  <title>Firebase Authentication sample 01</title>
  <script src="https://cdn.firebase.com/libs/firebaseui/3.5.2/firebaseui.js"></script>
  <link href="https://cdn.firebase.com/libs/firebaseui/3.5.2/firebaseui.css" rel="stylesheet" type="text/css">
</head>
<body>
  <h1>Firebase Authenction Sample 01</h1>
  <div id="auth"></div>
  <script src="/__/firebase/7.16.0/firebase-app.js"></script> 
  <script src="/__/firebase/7.16.0/firebase-auth.js"></script> 
  <script src="/__/firebase/init.js"></script> 
  <script type="text/javascript">

    /*
  Firebase Authentcation を使った認証サンプル 01
  Firebase Authentication UI を使い、サインイン用のUIを生成
  ポップアップウィンドウで認証画面を表示、サインイン後元の画面に移動
  サインアウト ボタンと、Googleの表示名をウェルカムメッセージとして表示
  サインアウト 用の関数「signOut」を定義

  */

  const ui = new firebaseui.auth.AuthUI(firebase.auth());
  const uiConfig = {
  callbacks: {
    signInSuccessWithAuthResult: function(authResult, redirectUrl) {
      return true;
    },
  },
  signInFlow: 'popup',
  signInSuccessUrl: 'auth-sample01.html',
  signInOptions: [
    firebase.auth.GoogleAuthProvider.PROVIDER_ID,
  ],
  tosUrl: 'sample01.html',
  privacyPolicyUrl: 'auth-sample01.html'
  };

  ui.start('#auth', uiConfig);

  firebase.auth().onAuthStateChanged(user => {
    if (user) {
        const signOutMessage = `
        <p>Hello, ${user.displayName}!<\/p>
        <button type="submit"  onClick="signOut()">サインアウト<\/button>
        `;
        document.getElementById('auth').innerHTML =  signOutMessage;
        console.log('ログインしています');

    } 
  });

  function signOut() {
  firebase.auth().onAuthStateChanged(user => {
    firebase
      .auth()
      .signOut()
      .then(() => {
        console.log('ログアウトしました');
        location.reload();
      })
      .catch((error) => {
        console.log(`ログアウト時にエラーが発生しました (${error})`);
      });
  });
  }

  </script>
</body>
</html>

独自UIで開発

基本はFirebase UIと変わらないです。

  • Firebase Authentication を使ってAuthオブジェクトを作成
  • 認証用のメソッドを呼び出し

となります。詳細は以下。

Google プロバイダ オブジェクトの作成

Firebase Authentication のSDKをロード後、プロバイダオブジェクトを生成します。


var provider = new firebase.auth.GoogleAuthProvider();

サインイン用のメソッドを呼び出す。


firebase.auth().signInWithPopup(provider).then(function(result) {

 // 認証後の処理を記述します

}).catch(function(error) {

 // エラー時の処理を記述します

});

認証用のメソッドはここにまとまっています。

認証後のユーザー情報

認証後のユーザー情報は「user」もしくは「userIInfo」メソッドで取得できます。

https://firebase.google.com/docs/reference/js/firebase.User
https://firebase.google.com/docs/reference/js/firebase.UserInfo


firebase.auth.user
firebase.auth.userinfo

サンプルコード

Authentication UI の時と同様、サンプルコードを書いてみました。仕様は以下の通りです。

  • ボタンを押すと、ポップアップウィンドウが表示され、Google で認証できる
  • 認証が成功したら、現在サインインしたユーザーの名前とメールアドレスがウェルカムメッセージとともに表示される
  • サインアウト ボタンを押すと初期状態に戻る

動作サンプルは こちら

サンプルコード
auth-sample02.html

<!DOCTYPE html>
<html lang="ja">
<head>
  <title>Firebase Authentication sample 02</title>
  <script src="https://cdn.firebase.com/libs/firebaseui/3.5.2/firebaseui.js"></script>
  <link href="https://cdn.firebase.com/libs/firebaseui/3.5.2/firebaseui.css" rel="stylesheet" type="text/css">
</head>
<body>
  <h1>Firebase Authenction Sample 02</h1>
  <div id="auth"></div>
  <script src="/__/firebase/7.16.0/firebase-app.js"></script> 
  <script src="/__/firebase/7.16.0/firebase-auth.js"></script> 
  <script src="/__/firebase/init.js"></script> 
  <script type="text/javascript">

  /*
  Firebase Authentcation を使った認証サンプル 02
  Google認証用のオブジェクトを生成
  認証用の関数「signIn」を定義
  サインアウト 用の関数「signOut」を定義
  認証の状態をチェックして、「サインイン」「サインアウト 」のボタンを出し分ける
  */

  const provider = new firebase.auth.GoogleAuthProvider();

  function signIn() {
  firebase.auth().signInWithPopup(provider)
  .then(result => {
      console.log('ログインしました。');

  }).catch(error => {
        const signinError = `
        サインインエラー
        エラーメッセージ: ${error.message}
        エラーコード: ${error.code}
        `
     console.log(signinError);
  });
  }

  function signOut() {
  firebase.auth().onAuthStateChanged(user => {
    firebase
      .auth()
      .signOut()
      .then(() => {
        console.log('ログアウトしました');
        location.reload();
      })
      .catch((error) => {
        console.log(`ログアウト時にエラーが発生しました (${error})`);
      });
  });
  }

  firebase.auth().onAuthStateChanged(user => {
    if (user) {
        const signOutMessage = `
        <p>Hello, ${user.displayName}!<\/p>
        <button class="btn btn-primary" type="submit"  onClick="signOut()">サインアウト<\/button>
        `;
        document.getElementById('auth').innerHTML =  signOutMessage;
        console.log('ログインしています');

    } else {
          const signInMessage = `
          <button class="btn btn-primary" type="submit"  onClick="signIn()">サインイン<\/button>
          `;
          document.getElementById('auth').innerHTML = signInMessage;       
    }
  });

  </script>
</body>
</html>

ユーザー情報取得のラグについて

Auhenticationで認証後、ウェブアプリでユーザー情報を取得しようとしてうまくいかない場合があります。

以下は、Firebaseのドキュメントに記述されている認証チェックのコードです。


var user = firebase.auth().currentUser;

if (user) {
  // User is signed in.
} else {
  // No user is signed in.
}

認証が完了して、サインインが済んでいる状態でこのコードを使うと、認証中のユーザー情報「currentUser」の情報をもとに色々な処理が行えます。

一方で、サインイン直後にこのコードを使おうとすると、オブジェクト生成が完了する前に処理が走り、エラーが発生するケースが多い。

これを避けるためには「onAuthStateChanged」でユーザーの状態をチェックしてから処理するとうまくいきます。

認証が成功していれば、onAuthStateChanged メソッドからユーザーデータが含まれたオブジェクトが返るため、このデータを元にゴニョゴニョします。


firebase.auth().onAuthStateChanged(function(user) {
  if (user) {
    // User is signed in.
  }
});

自分はPromiseオブジェクトを生成して、ユーザーオブジェクトをresolveしてからゴニョゴニョしてみました。


// Firebase Authentication のPromiseオブジェクトを生成する関数を定義

    function genUser() {
    return new Promise((resolve, reject) => {
      firebase.auth().onAuthStateChanged(user => {
        if (user) {
          resolve(user);
        } else {
          return null;
        }
      });
    });
  }

// Firebase の認証情報をResolveして処理ロジックに渡す

    Promise.resolve(genUser()).then(user =>{

    // user 内にGoogle認証を利用したユーザー情報が格納されている

    console.log(user.uid);
    console.log(user.displayName);

    });

113
86
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
113
86