Nuxt.jsとFirebaseでユーザー認証機能の実装（ パスワード, Facebook,Google ）

#はじめに
フロントエンドエンジニアにとってユーザー認証のバックエンドを用意するのは手間になることが多いですよね。
そんなときに頼りになるのがFirebase。
Firebaseを導入すると簡単にユーザー認証機能が導入できるのでその手順をまとめました。


##事前準備
以下を使用できる状態にしておきます。

- vue.js
- create-nuxt-app  

### Firebaseでプロジェクトの設定
下記Firebase Consoleにログインしてプロジェクトを作成します。
[Firebase Console](https://console.firebase.google.com/?hl=ja)

![スクリーンショット 2018-12-05 11.39.01.png](https://qiita-image-store.s3.amazonaws.com/0/85153/728d0968-1ecf-1f41-c376-089ab4daae03.png)

管理画面よりAuthを選択

![section2.jpg](https://qiita-image-store.s3.amazonaws.com/0/85153/d3e4c386-50e8-80e8-8580-aab4a0d9dcb3.jpeg)

ログインプロバイダの**メール/パスワード**、**Google**、**Facebook**を有効化します。

![スクリーンショット 2018-12-07 12.29.23.png](https://qiita-image-store.s3.amazonaws.com/0/85153/01eb6829-c52c-ca43-1757-bc5f95264c69.png)

Facebookに関してはアプリケーションの設定が必要になります。
事前に[Facebook for Developer](https://developers.facebook.com/?locale=ja_JP)よりアプリケーションを作成しておき**アプリID**と**アプリシークレット**を取得しておき登録します。

![section3.jpg](https://qiita-image-store.s3.amazonaws.com/0/85153/48b6514f-c7dd-963d-e81e-215259593c38.jpeg)

さらにリダイレクトURLをFacebookアプリケーションに設定します。


![section4.jpg](https://qiita-image-store.s3.amazonaws.com/0/85153/9dfc9041-d217-1ef0-9e49-a917ac14c95d.jpeg)

これで準備OK！

##Nuxtアプリケーションを作成  

今回はNuxtの雛形をそのまま使用します。
色々聞かれますが全てenterでOK、今回はパッケージマネージャーにyarnを選択します。

```
$ yarn create nuxt-app nuxt-login-app
```

**Firebaseモジュール**をインストールしておきます。

```
$ cd nuxt-login-app
$ yarn add firebase
```

こちらのコマンドでアプリを立ち上げ

```
$ yarn dev
```

アプリケーションが立ち上がりました。こちらで作成していきます。

![スクリーンショット 2018-12-05 12.08.18.png](https://qiita-image-store.s3.amazonaws.com/0/85153/9f8a2348-cc72-9583-72ac-a77b55344208.png)

##認証ページの作成

Google,Facebook,パスワードの順番にユーザー認証を実装していきます。

### 認証の準備

Firebase Consoleのこちらから認証情報を表示してAPI Key等の設定情報を表示します。

![seciton1.jpg](https://qiita-image-store.s3.amazonaws.com/0/85153/2846ca36-4364-52d9-4353-709293208f58.jpeg)

configの内容をコピー

![sample6.jpg](https://qiita-image-store.s3.amazonaws.com/0/85153/0147bb25-bd96-af20-0ffd-5bbd9f48a8d2.jpeg)


先ずはNuxtアプリケーションplugins内にfirebase.jsを作成してこちらの設定情報を利用します。

```plugins/firebase.js
import firebase from 'firebase'

const config = {
  apiKey: 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX',
  authDomain: 'nuxt-login-app.firebaseapp.com',
  databaseURL: 'https://nuxt-login-app.firebaseio.com',
  projectId: 'nuxt-login-app',
  storageBucket: 'nuxt-login-app.appspot.com',
  messagingSenderId: '611183763562'
}

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

export default firebase

```

### Google認証
まずはGoogle認証からpages/index.vueを書き換えます。
今回はリダイレクト方式を採用。
読み込み時に**onAuthStateChanged**でログイン状態をチェック。
ボタンクリックで**googleLogin**メソッドを実行。
それぞれFirebaseモジュールで用意されたオブジェクトを使用するので簡単に実装可能です。

[Google ログイン ドキュメント](https://firebase.google.com/docs/auth/web/google-signin)

```pages/index.vue
<template>
  <section class="container">
    <div v-if="isWaiting">
      <p>読み込み中</p>
    </div>
    <div v-else>
      <div v-if="!isLogin">
        <button @click="googleLogin">Googleでログイン</button>
      </div>
      <div v-else>
        <p>{{ user.email }}でログイン中</p>
        <button @click="logOut">ログアウト</button>
      </div>
    </div>
  </section>
</template>

<script>
import firebase from '@/plugins/firebase'

export default {
  asyncData () {
    return {
      isWaiting: true,
      isLogin: false,
      user: []
    }
  },
  mounted: function () {
    firebase.auth().onAuthStateChanged(user => {
      this.isWaiting = false
      if (user) {
        this.isLogin = true
        this.user = user
      } else {
        this.isLogin = false
        this.user = []
      }
    })
  },
  methods: {
    googleLogin () {
      const provider = new firebase.auth.GoogleAuthProvider()
      firebase.auth().signInWithRedirect(provider)
    },
    logOut () {
      firebase.auth().signOut()
    }
  }
}
</script>
```

### Facebook認証
Facebookも基本的にはGoogleと同じです。
[Facebook認証 ドキュメント](https://firebase.google.com/docs/auth/web/facebook-login)

```pages/index.vue
<template>
  <section class="container">
    <div v-if="isWaiting">
      <p>読み込み中</p>
    </div>
    <div v-else>
      <div v-if="!isLogin">
        <button @click="facebookLogin">Facebookでログイン</button>
      </div>
      <div v-else>
        <p>{{ user.email }}でログイン中</p>
        <button @click="logOut">ログアウト</button>
      </div>
    </div>
  </section>
</template>

<script>
import firebase from '@/plugins/firebase'

export default {
  asyncData () {
    return {
      isWaiting: true,
      isLogin: false,
      user: []
    }
  },
  mounted: function () {
    firebase.auth().onAuthStateChanged(user => {
      this.isWaiting = false
      if (user) {
        this.isLogin = true
        this.user = user
      } else {
        this.isLogin = false
        this.user = []
      };
    })
  },
  methods: {
    facebookLogin () {
      const provider = new firebase.auth.FacebookAuthProvider()
      firebase.auth().signInWithRedirect(provider)
    },
    logOut () {
      firebase.auth().signOut()
    }
  }
}
</script>
```

###パスワード認証
パスワード認証はemailとpasswordを渡すだけです。
パスワードの文字数が6文字以上などの決まりがあるのでその辺りのバリデーションを適切に設定してください。
こちらは新規登録とログインで手順が違うのでregisterステータスで場合分けしています。
[パスワード認証 ドキュメント](https://firebase.google.com/docs/auth/web/password-auth)

```pages/index.vue
<template>
  <section class="container">
    <div v-if="isWaiting">
      <p>読み込み中</p>
    </div>
    <div v-else>
      <div v-if="!isLogin">
        <div>
          <p>
            <input
              v-model="email"
              type="text"
              placeholder="email"
            >
          </p>
          <p>
            <input
              v-model="password"
              type="password"
              placeholder="password"
            >
          </p>
          <p>
            <input
              id="checkbox"
              v-model="register"
              type="checkbox"
            >
            <label for="checkbox">新規登録</label>
          </p>
          <button @click="passwordLogin">{{ register ? '新規登録' : 'ログイン' }}</button>
          <p>{{ errorMessage }}</p>
        </div>
      </div>
      <div v-else>
        <p>{{ user.email }}でログイン中</p>
        <button @click="logOut">ログアウト</button>
      </div>
    </div>
  </section>
</template>

<script>
import firebase from '@/plugins/firebase'

export default {
  asyncData () {
    return {
      register: false,
      isWaiting: true,
      isLogin: false,
      user: [],
      email: '',
      password: '',
      errorMessage: ''
    }
  },
  mounted: function () {
    firebase.auth().onAuthStateChanged(user => {
      this.isWaiting = false
      this.errorMessage = ''
      if (user) {
        this.isLogin = true
        this.user = user
      } else {
        this.isLogin = false
        this.user = []
      };
    })
  },
  methods: {
    passwordLogin () {
      const email = this.email
      const password = this.password
      if (this.register) {
        firebase.auth().createUserWithEmailAndPassword(email, password).catch(function (error) {
          const errorMessage = error.message
          this.errorMessage = errorMessage
        }.bind(this))
      } else {
        firebase.auth().signInWithEmailAndPassword(email, password).catch(function (error) {
          const errorMessage = error.message
          this.errorMessage = errorMessage
        }.bind(this))
      }
    },
    logOut () {
      firebase.auth().signOut()
    }
  }
}
</script>
```

Firebase Consoleで各認証方法で登録したユーザーの追加が確認できました。
GUIで追加、編集等の管理ができるのが便利ですね。

![sample5.jpg](https://qiita-image-store.s3.amazonaws.com/0/85153/f736c9e4-8c22-e0a7-a3d6-e80371b28efd.jpeg)

##最後に


Firebaseのログイン認証は以外にもデータベースやサーバー等フロントエンジニアにとって助かる機能がいくつもあるのでもっと活用していきたいですね。