Nuxt + Rails + Firebase ユーザー登録 (Nuxt編)

Nuxt + Rails + Firebase ユーザー登録 (Nuxt編)

今回はユーザーの認証をfirebaseを使用して行います。

もしまだCRUDの機能を実装していない方は環境構築だけ先にしてこの記事に戻ってくることをオススメします。

Nuxt Rails環境構築

Firebaseとは

Firebase は Google が提供しているモバイルおよび Web アプリケーションのバックエンドサービスです。

https://www.topgate.co.jp/firebase01-what-is-firebase

機能としてRealtime DatabaseやCloud firestoreなどいくつか用意されています。

今回はその中の一つFirebase Authenticationを使用します。

Firebase Authentication には、バックエンド サービス、使いやすい SDK、アプリでのユーザー認証に使用できる UI ライブラリが用意されています。Firebase Authentication では、パスワード、電話番号、一般的なフェデレーション ID プロバイダ(Google、Facebook、Twitter)などを使用した認証を行うことができます。

firebaseドキュメント

Firebaseセットアップ

Firebaseのコンソール にアクセスしてプロジェクト作成ボタンを押してください。(ユーザーのサインインがまだの方はサインインしてください。)

プロジェクト名を入力画面が表示されるのでプロジェクト名を入力します。

Googleアナリティクスを有効にするかを聞かれますが今回は使用しないのでチェックを外して「プロジェクトを作成」を押します。

プロジェクトの作成が完了すると下記のような画面が表示されます。

「続行」を押してください。

プロジェクトの概要の横の歯車マークをクリックして「プロジェクトを設定」を選択します。

アプリを登録します。

アプリのニックネームに任意の名前を入力してください。

入力が完了したら「アプリを登録」ボタンをクリックします。

マイアプリの「構成」にチェックをすると下記のように表示されればひとまず完了です。こちらはあとで使用します。

Authenticationの機能を追加していきます。

「Authentication」をクリックしてください。

「始める」をクリック

メール/パスワードを編集します。

「有効にする」にチェックし保存してください。

これでfirebaseのセットアップはひとまず終了です。

次にNuxt側でfirebaseを使用できるようにセットアップします。

// firebaseのインストール
front $ npm install -g firebase-tools

// バージョン確認
front $ firebase --version           
9.5.0

// gmailでfirebaseにログインする
front $ firebase login

// firebaseインストール
front $ yarn add firebase

続いてapi_keyの設定をしていくのですがキーを直書きしたくないので、envファイルを作成します。

front $ yarn add @nuxtjs/dotenv

configディレクトリを作成してそこに.env.localファイルを作成します。

ここに先ほどのfirebaseのマイアプリの構成の値を入れます。

front/config/.env.local

API_KEY=XXXXXXXXXXXXX
AUTH_DOMAIN=XXXXXXXXXXXXX
PROJECT_ID=XXXXXXXXXXXXX
STORAGE_BUCKET=XXXXXXXXXXXXX
MESSAGE_SENDER_ID=XXXXXXXXXXXXX
APP_ID=XXXXXXXXXXXXX

続いてnuxt.configを修正してenvに記述した値をアプリ上で使用できるようにします。

front/nuxt.config.js
const envPath = `config/.env.${process.env.ENV || 'local'}`
require('dotenv').config({ path: envPath })

export default {
  ..省略

  env: {
    apiKey: process.env.API_KEY,
    authDomain: process.env.AUTH_DOMAIN,
    projectId: process.env.PROJECT_ID,
    storageBucket: process.env.STORAGE_BUCKET,
    messageSenderId: process.env.MESSAGE_SENDER_ID,
    appId: process.env.APP_ID,
  },
}

最後にfirebaseのpluginsを作成し読み込むようにします。

plugins/firebase.js

import firebase from 'firebase/app'
import "firebase/auth"

const firebaseConfig = {
  apiKey: process.env.apiKey,
  authDomain: process.env.authDomain,
  databaseURL: process.env.databaseURL,
  projectId: process.env.projectId,
  storageBucket: process.env.storageBucket,
  messagingSenderId: process.env.messagingSenderId,
  appId: process.env.appId,
}

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

export default firebase

これでfirebaseのセットアップが完了したのでconsoleでfirebaseに接続できるかを確認します。

front/pages/index.vue

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

export default {
  data: () => {
    return {
      message: ''
    }
  },

  mounted() {
    console.log(firebase.auth())
  }
}
</script>

コンソールに以下のような表示されればfirebaseを使用できるようになっています。

Plugin 設定

firebaseのセットアップが完了したので次は現在ログインしているユーザーがいなければログイン画面に遷移するようにpluginを設定していきます。

まず必要なファイルを用意します。

  • pluginsディレクトリにauthentication.jsを作成
  • pagesディレクトリにlogin.vueを作成

login.vue

front/pages/login.vue

<template>
  <div>
    ログイン画面です
  </div>
</template>

authentication.js

front/plugins/authentication.js

import firebase from '~/plugins/firebase'

export default function ({ route, redirect }) {
  firebase.auth().onAuthStateChanged(function(user) {
    if (user) {
      // User is signed in.
    } else {
      // No user is signed in.
      if (route.path !== '/login') {
        redirect('/login')
      }
    }
  });
}

onAuthStateChanged で現在ログインしているユーザーを取得します。

現在ログインしているユーザーを取得する-firebase

これでログインしていない場合はログイン画面に遷移するようになりました。

ログイン画面作成

次はログイン画面を作成して実際にログインできるように実装します。その前にfirebaseに仮のユーザーを作成します。

firebase Authenticationで適当にユーザーを追加します。

コンソールにユーザーを作成できたので次にログイン画面を作成します。

front/pages/login.vue

<template>
  <v-card max-width="500" class="mt-10 mx-auto">
    <v-snackbar
      v-model="snackbar"
      color="error"
      top
      right
    >
      {{ message }}
    </v-snackbar>
    <v-card-text>
      <v-container>
        <v-row>
          <v-col cols="12">
            <v-text-field
              v-model="email"
              label="メールアドレス"
              required
            />
          </v-col>
          <v-col cols="12">
            <v-text-field
              v-model="password"
              :append-icon="isPasswordShow ? 'mdi-eye' : 'mdi-eye-off'"
              :type="isPasswordShow ? 'text' : 'password'"
              label="パスワード"
              @click:append="isPasswordShow = !isPasswordShow"
            />
          </v-col>
        </v-row>
      </v-container>
    </v-card-text>
    <v-card-actions>
      <v-spacer></v-spacer>
      <div class="w-100 px-4">
        <v-btn
          x-large
          color="blue"
          block
          class="mx-auto mb-5"
          @click="login()"
        >
          ログイン
        </v-btn>
      </div>
    </v-card-actions>
  </v-card>
</template>

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

export default {
  data: () => {
    return {
      email: '',
      password: '',
      isPasswordShow: false,
      message: '',
      snackbar: false,
    }
  },
  methods: {
    login() {
      firebase.auth()
        .signInWithEmailAndPassword(this.email, this.password)
        .then(() => {
          // Signed in
          // ...
          this.$router.push('/')
        })
        .catch(() => {
          this.message = 'メールアドレスまたはパスワードが正しくありません'
          this.snackbar = true
        });
    },
  }
}
</script>

<style scoped>
.w-100 {
  width: 100%;
}
</style>

signInWithEmailAndPassword() メソッドを使用してメールアドレスとパスワードの組み合わせでログインできます。

ログインに成功したらトップページに遷移します。ログインに失敗したらエラーメッセージを表示します。

これでfirebase コンソールに存在するデータでログインはできました。

しかしこのままだとコンソールに存在するデータでしかログインできないので次はアプリ上でユーザーを新規作成できるようにします。

ユーザー新規作成

まずはログイン画面に新規作成画面へのリンクを作成します。

front/pages/login.vue

    <v-card-actions>
      <v-spacer></v-spacer>
      <div class="w-100 px-4">
        <v-btn
          x-large
          color="blue"
          block
          class="mx-auto mb-5"
          @click="login()"
        >
          ログイン
        </v-btn>
      </div>
    </v-card-actions>

    <div class="mx-auto text-center pb-5">
      <nuxt-link to="/signup">
        新規登録はこちら
      </nuxt-link>
    </div>
  </v-card>
</template>

次にsignupページを作成します。

front/pages/signup.vue

<template>
  <v-card max-width="500" class="p-4 mt-10 mx-auto">
    <v-snackbar
      v-model="snackbar"
      color="error"
      top
      right
    >
      {{ message }}
    </v-snackbar>
    <v-card-text>
      <v-container>
        <v-row>
          <v-col cols="12">
            <v-text-field
              v-model="email"
              label="メールアドレス"
              required
            />
          </v-col>
          <v-col cols="12">
            <v-text-field
              v-model="password"
              :append-icon="isPasswordShow ? 'mdi-eye' : 'mdi-eye-off'"
              :type="isPasswordShow ? 'text' : 'password'"
              label="パスワード"
              @click:append="isPasswordShow = !isPasswordShow"
            />
          </v-col>
        </v-row>
      </v-container>
    </v-card-text>
    <v-card-actions>
      <v-spacer></v-spacer>
      <div class="w-100 px-4">
        <v-btn
          x-large
          color="blue"
          block
          class="mx-auto mb-5"
          @click="login()"
        >
          新規登録
        </v-btn>
      </div>
    </v-card-actions>
  </v-card>
</template>

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

export default {
  data: () => {
    return {
      email: '',
      password: '',
      isPasswordShow: false,
      message: '',
      snackbar: false,
    }
  },
  methods: {
    login() {
      firebase.auth()
        .createUserWithEmailAndPassword(this.email, this.password)
        .then(() => {
          this.$router.push('/')
        })
        .catch((error) => {
          this.setErrorMessage(error.code)
          this.snackbar = true
        });
    },
    setErrorMessage(errorCode) {
      switch (errorCode) {
        case 'auth/invalid-email':
          this.message = 'メールアドレスの形式に誤りがあります。'
          break
        case 'auth/email-already-in-use':
          this.message = '入力されたメールアドレスは既に使用されています。'
          break
        case 'auth/weak-password':
          this.message = 'パスワードは6文字以上で入力してください。'
          break
        default:
          this.message = '新規登録に失敗しました。'
          break
      }
    },
  }
}
</script>

<style scoped>
.w-100 {
  width: 100%;
}
</style>

createUserWithEmailAndPassword() メソッドを使用してメールアドレスとパスワードの組み合わせでユーザーを作成します。

新規登録に成功するとトップページに遷移します。失敗するとエラーメッセージが表示されます。

firebaseコンソールにユーザーが作成されているのを確認できました。

以上でfirebaseを使用したユーザー認証の実装が完了しました。他にもメール認証やパスワードリセット等もあるのでぜひ公式ドキュメントを見ながら実装してみてください。

次の記事はこちら: Nuxt + Rails + Firebase ユーザー登録 (Rails編)

参考: https://qiita.com/minuro/items/df5612117f7bfb5c1d53

Rails + Nuxtカテゴリの最新記事