Nuxt.jsでFirebase REST APIを使ったサインアップ・ログイン機能の作り方

Vue.js

Nuxt.jsでFirebase REST APIを使ったサインアップ・ログイン機能の作り方を紹介します。

Nuxt.jsでFirebase REST APIを使ったサインアップ機能の作り方

Firebase Authenticationを使用

まだサービスを使ったことがない人が、メールアドレスとパスワードで新規登録してサインアップできる機能を作ります。
Firebaseのプロジェクトを作成したら、Authenticationの「始める」をクリックします。
そして、サインアップの方法を選択します。
Authentication
メールとパスワードであれば、上のように有効にして保存します。

Firebase認証REST APIのページでエンドポイントURLを取得

Firebase認証REST APIのページを訪れます。

そして、エンドポイントがリクエストを送る先なので、メール・パスワードでサインアップという項目を探して、そのエンドポイントに記載されているURLをコピーします。
https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=[API_KEY]

FirebaseのAPI_KEYを取得

この[API_KEY]の部分は、Firebaseで入手する必要があるので、プロジェクトの概要、アプリの追加でwebを選択してapikeyを取得します。

Firebaseの詳しい使い方に関しては、Nuxt.jsでfirebaseを使う方法を参考にしてみてください。

pages/auth/index.vueを作成

<template>
  <div class="admin-auth-page">
    <div class="auth-container">
      <form @submit.prevent="onSubmit">
        <AppInput type="email">Eメール</AppInput>
        <AppInput type="password">パスワード</AppInput>
        <AppButton type="submit">{{ isLogin ? 'ログイン' : 'サインアップ' }}</AppButton>
        <AppButton
          type="button"
          btn-style="inverted"
          style="margin-left: 10px"
          @click="isLogin = !isLogin">{{ isLogin ? 'サインアップ' : 'ログイン' }}へ切り替える</AppButton>
      </form>
    </div>
  </div>
</template>

formタグでは、@submitで即座にページ更新されると困るのでpreventをつけます。


axiosをグローバルに設定していないのなら、上のようにインポートします。

firebase email password auth

リクエストボディペイロードで、メールアドレス、パスワード、returnSecureTokenを設定する必要があると記載があるので、そのオブジェクトを用意します。
そのために、まずは、templateで、emailとpasswordにv-modelを追加します。

<AppInput type="email" v-model="email">Eメール</AppInput>
<AppInput type="password" v-model="password">パスワード</AppInput>

そしてdataに初期値を設定します。

  data() {
    return {
      ...
      email: '',
      password: ''
    }
  },

そして、オブジェクトを作成します。

 {
        email: this.email,
        password: this.password,
        returnSecureToken: true,
      }

Nuxt.jsでFirebase REST APIを使ったサインイン・ログイン機能の作り方

すでに登録している人が、ログインできるようにする機能を作ります。
サインアップのときとほとんど同じですが、リクエストを送る先が変わります。
メール・パスワードでサインインという項目を探して、そのエンドポイントに記載されているURLをコピーします。
>>>サインイン(ログイン)の場合の公式サイト
https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=[API_KEY]
[API_KEY]の部分は、Firebaseで入手したものを使います。
サインイン・ログイン
リクエストボディペイロードの内容もログインとサインアップは同じです。

ログインとサインアップの処理をまとめる

ログインとサインアップの処理は同じで、URLのみが異なるので、次のようにscriptを書き換えます。

<script>
import axios from 'axios'

export default {
  data() {
    return {
      isLogin: true,
      email: '',
      password: ''
    }
  },
  methods: {
    onSubmit() {
      // デフォルトのURL(ログインとする)を設定
      let authUrl = `https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=${process.env.firebaseAPIkey}`

      // ログインモードでない場合、サインアップのURLをセット
      if(!this.isLogin) {
          authUrl = `https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=${process.env.firebaseAPIkey}`
      }
      // ログイン/サインアップの処理
      axios.post(authUrl, {
          email: this.email,
          password: this.password,
          returnSecureToken: true,
        })
        .then(result => {
          console.log(result)
        })
        .catch(e => console.log(e))
      }
  }
}</script>

リクエストを送る先であるエンドポイントのURLを変数authUrlに格納して、isLoginで切り替えます。
その後、ログイン・サインアップの処理を記述します。

vuexでTokenを保持する

pages/auth/index.vue

処理内容はsctionsに移動するので、pages/auth/index.vueは、dispatchします。

  methods: {
    // ユーザー認証
    onSubmit() {
      this.$store.dispatch('authUser', {
        isLogin: this.isLogin,
        email: this.email,
        password: this.password
      })
      // actionsでaxiosをreturnしているのでthen()が使える
      .then(() => {
        this.$router.push('/admin')
      })
    }
  }

Firebaseのtokenを格納するためのstate、
それを保持できるようにするためのmutation、
authUserというactionをstore/index.jsに記述します。

store/index.js

state

    state: {
      token: null, //ユーザー認証
    },

tokenを格納したいのでまずはstateに変数を用意します。

mutations

    mutations: {
      // ユーザー認証のmutation、tokenをセット
      setToken(state, token) {
        state.token = token
      },
    },

tokenをstateにセットするためにmutationを作成します。

actions

    actions: {
      // ユーザー認証のaction
      authUser(vuexContext, authData) {
        // デフォルトのURL(ログインとする)を設定
        let authUrl = `https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=${process.env.firebaseAPIkey}`

        // ログインモードでない場合、サインアップのURLをセット
        if(!authData.isLogin) {
            authUrl = `https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=${process.env.firebaseAPIkey}`
        }
        // ログイン/サインアップの処理
        return axios.post(authUrl, {
            email: authData.email,
            password: authData.password,
            returnSecureToken: true,
        })
        .then(result => {
          vuexContext.commit('setToken', result.data.idToken)
        })
        .catch(e => console.log(e))
      },
    },

そして、actionを設定します。
axiosのモジュールを使っている場合は、then()ブロックはresultやresponseではなく、dataにダイレクトにアクセスできるので、result.data.idTokenではなく、data.idTokenとすることでアクセスできます。

IDトークンによる認証

Realtime Databaseのルールを次のようにauthされている状態でないとwriteできないとします。

{
  "rules": {
    ".read": "true",
    ".write": "auth != null",
  }
}

その場合、ログインしているユーザーしたwriteできなくなります。
そして、上のようにIDを保持しただけでは、データを送信してもエラーが返されてしまいます。
認証されたリクエストをRealtime Database REST APIに送信するには、vuexのstateのtokenに保持したIDトークンをauth=というクエリ文字列パラメータとして渡す必要があります。

Firebase公式サイト:IDトークンによる認証によると、
"https://.firebaseio.com/users/ada/name.json?auth="
というURLのため、?auth=というパラメーターとIDトークンを記述すればいいことがわかります。

よって、actionsで、

editPost(vuexContext, post) {
return axios.put(`${process.env.baseUrl}/posts/${post.id}.json`, オブジェクト)
...
}

という部分を下のように変更します。

editPost(vuexContext, post) {
return axios.put(`${process.env.baseUrl}/posts/${post.id}.json?auth=${vuexContext.state.token}`, オブジェクト)
...
}

stateには、vuexContextからアクセスできます。

これでIDトークンによって認証されている状態となります。

middlewareを使ってログインしていないユーザーをリダイレクトするには、middlewareを使ってログインしていないユーザーをリダイレクトする方法を参考にしてみてください。

Vue.js

Posted by devsakaso