Vue × Firebase Authenticationで認証情報を渡す

Firebaseって便利ですよね。
各種SNS認証や、ログイン認証、パスワード再発行などのユーザー登録やログイン周りから始まってFirestoreやFirestorageと、サーバーサイドの知識がほぼ0でもウェブサービスを実装することが出来てしまいます。
（断っておきますが、エンジニアとしてはサーバーサイドの知識もあるに越したことはないので、学習頑張りましょう。筆者も引き続き学習していきます。）

※記事内で使用している、クラス名やaction-typesの命名に関しては簡易的なものになりますので、参考にしないようお願いします。

## よく見るあれをFirebaseで実装する
ログイン認証が必要なサービスで、ログイン後のページやダッシュボード・ユーザーページでこういうURLを見ることってありますよね。

```
https://hogefuga.com/user=OgWGQbLI4FrN4gOlcHpxyPAeG/mypage
```

また、ダッシュボードのデザインでよく、ユーザーサムネイルやユーザー名が表示されているものを目にすることも多いと思います。
今回はVue・Vuex・VueRouterとFirebaseを使用してこれを実装する方法を紹介します。

## Vuex
順番が前後してしまいますが、Vuex側の処理から記載していきます。
**actions.js**

```javascript
import firebase from '../../plugins/firebase.js'
import { T } from './types'

export const actions = {
  [T.AJAX_LOGIN_GOOGLE_AUTH] ({ commit }) {
    let provider = new firebase.auth.GoogleAuthProvider()
    firebase.auth().signInWithPopup(provider)
      .then((result) => {
        commit(T.AJAX_LOGIN_GOOGLE_AUTH, result.user)
      })
      .catch((err) => {
        console.log(err)
      })
  },
}
```

**mutations.js**

```javascript
import { T } from './types'

export const mutations = {
  [T.AJAX_LOGIN_GOOGLE_AUTH] (state, resObj) {
    state.userInfo.data.uid = resObj.uid
    state.userInfo.data.displayName = resObj.displayName
    state.userInfo.data.email = resObj.email
    state.userInfo.data.providerId = resObj.providerData[0].providerId
    state.userInfo.data.photoUrl = resObj.photoURL
    state.isAutheniticated = true
  }
}
```

**getters.js**

```javascript
export const getters = {
  _getSigninUserInfo (state) {
    let data = state.userInfo.data
    return data
  }
}
```
Vuex側は、これといって特殊なことはしません。
actions.jsでFirebaseのAuthenticationの箇所を実装していきます。
今回はGoogle認証のsignInWithPopupを使用します。

mutationsでは今後の画面で使用することも兼ねて、 ログイン判定のBooleanをtrueにしておきます。


## ログインページ
```vuejs
<template>
  <div class="p-enterprise_signin" ref="enterpriseSignin">
    <div class="p-enterprise_signin_content">
      <h3>ログイン</h3>
      <button type="button" class="a-global_btn --google" @click="googleAuth">Google認証</button>
    </div>
  </div>
</template>

<script>
import { T as G } from '../../../store/modules/types'

export default {
  methods: {
    async googleAuth () {
      await this.$store.dispatch(`modules/${G.AJAX_LOGIN_GOOGLE_AUTH}`)
      this.$router.push('/enterprise/cmnEventHandler')
    }
  }
}
</script>
```
ログインページでは、ログイン用のボタンを用意し、methodsで先程定義したactionsへdispatchイベントを記述します。
このとき肝になるのが、JavaScriptのasync/awaitです。
これで、ログイン認証の処理が完了するまで一度処理を待たせます。

signInWithPopupを使用すると、ポップアップが表示している最中に遷移を行ってしまうため、このmethods内で直接遷移させたいページへ遷移を行ってしまうと、取得したデータがまだstateに保持されておらず、getters等で取得を行ってもundefinedになってしまいます。
こうなると実装したい

```
https://hogefuga.com/user=OgWGQbLI4FrN4gOlcHpxyPAeG/mypage
```
こんな感じのURLにすることが出来ません。
それを回避するために一度、以下のような空の画面を挟みます。


```vuejs
<template>
  <div></div>
</template>

<script>
import { mapGetters } from 'vuex'

export default {
  computed: {
    ...mapGetters('modules', {
      myData: '_getSigninUserInfo',
      isAutheniticated: '_getIsAutheniticated'
    })
  },
  mounted () {
    if (this.isAutheniticated) {
      this.$router.push({ path: `/enterprise/loginUser=${this.myData.uid}/dashboard` })
    }
  }
}
</script>
```
ここで、computedで取得することでログイン時に取得したuidやdisplayName等々を受け取ることが可能になるので、念願のuidつきURLが実装可能になります。


## まとめ
いかがでしたでしょうか。
ちょっと面倒な処理になってしまいますし、そもそもURLにuidないしユーザー識別目的の固有文字列を実装することがセキュリティの観点から果たして問題ないのかどうかも疑問ではありますが、よく見るため一度は実装してみたいと思う方もいらっしゃるかと思います。

ぜひ試してみてください。