l12a

白ウサギを追え

開発進捗「ユーザ登録が必要なサービスを Firebase Authentication で作る」編

Treee では作ったデータを永続化して後から編集を再開したり、別の端末からも利用できるようにします。
ユーザ毎にデータを保存してアクセス権限をコントロールするために Firebase Authentication を使ってユーザ登録機能を作成しました。
本記事では Firebase プロジェクトの初期化などは済んでいることを前提とし、また Firebase 自体のドキュメントは公式が充実していますので、 Vue.js や vuex を使ったアプリケーションコード上でどのように取り扱ったかを中心に以下の内容を解説します。

  • vuex action 上に実装したユーザ認証機能全体
  • Google アカウントを使ってユーザ登録する
  • サインインする
  • サインアウトする
  • サインイン状況に応じて UI を制御する

vuex action 上に実装したユーザ認証機能全体

まずは本記事で解説するユーザ登録機能を vuex action に実装した状態のコード全貌です。

import * as types from './mutation-types'

import * as firebase from 'firebase/app'
import 'firebase/auth'

import firebaseConfig from '../../firebaseConfig'

if (!firebase.apps.length) {
  firebase.initializeApp(firebaseConfig)
}

const provider = new firebase.auth.GoogleAuthProvider()

const authActions = {
  initialize ({ commit }) {
    firebase.auth().onAuthStateChanged((user) => {
      if (user) {
        commit(types.UPDATE_USER_ID, user.uid)
        commit(types.UPDATE_DISPLAY_NAME, user.displayName)
        commit(types.UPDATE_AUTHORIZED, true)
      } else {
        commit(types.UPDATE_USER_ID, '')
        commit(types.UPDATE_DISPLAY_NAME, '')
        commit(types.UPDATE_AUTHORIZED, false)
      }
      commit(types.UPDATE_INITIALIZED, true)
    })
  },
  signInWithGoogleAccount () {
    firebase.auth().signInWithRedirect(provider)
  },
  signOut () {
    firebase.auth().signOut()
  }
}

export default authActions

Google アカウントを使ってユーザ登録する

ユーザ登録は Google アカウントを使います。 Firebase Authentication では Google アカウントの他にも facebooktwitter など様々なアカウントが使えます。

f:id:lnly:20190410214137p:plain
Firebase Authentication で使用可能なアカウント

Treee でも認証に使えるアカウントを増やしていきたいです。

vuex store の actions 内で Firebase SDK を初期化する

Firebase Authentication を使用するためにはまず Firebase SDK を初期化します。
Firebase Authentication モジュールを import して、

import * as firebase from 'firebase/app'
import 'firebase/auth'

次に初期化に必要な API キーなどを別ファイルに切り出した firebaseConfig を import します。

import firebaseConfig from '../../firebaseConfig'

firebaseConfig の中身は、以下の通りです。

export default {
  apiKey: "<API_KEY>",
  authDomain: "<PROJECT_ID>.firebaseapp.com",
  databaseURL: "https://<DATABASE_NAME>.firebaseio.com",
  projectId: "<PROJECT_ID>",
  storageBucket: "<BUCKET>.appspot.com",
  messagingSenderId: "<SENDER_ID>",
 }

各種データは firebase コンソールのプロジェクト概要ページから、Web アプリを追加を選択するとデータが表示されます。

f:id:lnly:20190410214305p:plain
Firebase SDK の初期化に必要なデータの取得方法

画像ではマスクしているものの、このデータはクライアント側に露出しないよう特別に隠匿する必要はありません。

最後に initializeApp() を使って初期化します。

if (!firebase.apps.length) {
  firebase.initializeApp(firebaseConfig)
}

Google アカウントを使ってユーザ登録をするためのアクション実装

認証に使う GoogleAuthProvider()を new して、

const provider = new firebase.auth.GoogleAuthProvider()

signInWithRedirect() を使ってリダイレクトを伴う認証フローを呼び出します。
リダイレクトではなくポップアップウィンドウを開いて認証フローを呼び出すこともできますので、アプリケーションの性質によって好きな方を選べます。

signInWithGoogleAccount () {
  firebase.auth().signInWithRedirect(provider)
}

ここまでで、 Google アカウントを使ったユーザ登録のための vuex action は実装できました。

サインインする

サインインは、先に作成したアクションを vue コンポーネント上の任意の UI に割り当てて行います。

<template>
  <button
    type="button"
    @click="signInWithGoogleAccount"
  >サインインする</button>
</template>

<script>
import Vue from 'vue'
import { createNamespacedHelpers } from 'vuex'

const authStore = createNamespacedHelpers('authStore')

export default Vue.extend({
  methods: {
    ...authStore.mapActions(['signInWithGoogleAccount'])
  }
})
</script>

「サインインする」をクリックすれば画面が切り替わり、認証フローに入り、完了次第元の画面にリダイレクトで戻ってきます。

f:id:lnly:20190410214519p:plain
Google アカウントを使う認証フローへ遷移したところ

サインアウトする

サインアウトするためのアクションはこれだけです。

signOut () {
  firebase.auth().signOut()
}

サインインと同様に UI 側は任意のコンポーネントでこのアクションを割り当てて呼び出せばサインアウトします。

認証状況に応じて UI を制御する

サインインまたはサインアウトして認証状況が変化した時、 UI の表示や画面遷移などをコントロールするため、認証状況を vuex store に保持して利用します。

initialize ({ commit }) {
  firebase.auth().onAuthStateChanged((user) => {
    if (user) {
      commit(types.UPDATE_USER_ID, user.uid)
      commit(types.UPDATE_DISPLAY_NAME, user.displayName)
      commit(types.UPDATE_AUTHORIZED, true)
    } else {
      commit(types.UPDATE_USER_ID, '')
      commit(types.UPDATE_DISPLAY_NAME, '')
      commit(types.UPDATE_AUTHORIZED, false)
    }
    commit(types.UPDATE_INITIALIZED, true)
  })
}

onAuthStateChanged() にコールバックを登録すれば、認証状況が変化すると直ちにこれを呼び出して vuex state を書き換える mutation を commit できます。
この action をアプリケーションの初期化時に1回呼び出し、 UI は initialized や autorized の state を使って

  • 初期化して準備が終わるまで画面を表示しない
  • 認証されていなければ認証を促す

などのダイナミックな制御が可能になりました。
また UI 上に表示したい display name や、URL パラメータとして利用したい UID なども保持しました。

おしまい

Firebase のおかげで、ユーザ登録と認証を簡単に実現できました! 進捗報告はここまでです。
関連が深い公式ドキュメントはこの辺りになります。

firebase.google.com