🔑 Nuxt.js + Firebase Authentication

2020-11-26 #Development

Nuxt.js + Firebase Authentication のログイン機能の実装は当面個人開発でよく使いそうな組み合わせなんだけど、色々な場所に細々と記述しなければならなくてややこしいので忘れないようにメモ。

Firebase のコンソールとかでの設定方法は書いてたら長くなるのでコード部分のみ。

使用するパッケージを追加

まずは yarn で必要なパッケージを追加。

$ yarn add dotenv firebase vuex vuex-persistedstate

Firebase の設定

環境変数を dotenv で管理

環境変数周りは .env に記載して .gitignore に追加。

.env:

BASE_URL=https://xxxx-xxxxx.web.app/
APIKEY=xxxxxxxxxx
AUTHDOMAIN=xxxx-xxxxx.firebaseapp.com
DATABASEURL=https://xxxx-xxxxx.firebaseio.com
PROJECTID=xxxx-xxxxx
STORAGEBUCKET=xxxx-xxxxx.appspot.com
MESSAGINGSENDERID=000000000000

設定ファイルに下記みたいに入れておくと process.env.APIKEY とかで呼び出せるようになります。

nuxt.config.js:

require("dotenv").config();

export default {
  //...

  env: {
    APIKEY: process.env.APIKEY,
    AUTHDOMAIN: process.env.AUTHDOMAIN,
    DATABASEURL: process.env.DATABASEURL,
    PROJECTID: process.env.PROJECTID,
    STORAGEBUCKET: process.env.STORAGEBUCKET,
    MESSAGINGSENDERID: process.env.MESSAGINGSENDERID,
  },

  //...
};

/plugin で Firebase の初期化

インポートは "firebase" ではなく "firebase/app" として、あとは必要な物だけ追加するようにします。

/plugin/firebase.js:

import firebase from "firebase/app";
import "firebase/auth";
import "firebase/firestore";

if (!firebase.apps.length) {
  firebase.initializeApp({
    apiKey: process.env.APIKEY,
    authDomain: process.env.AUTHDOMAIN,
    databaseURL: process.env.DATABASEURL,
    projectId: process.env.PROJECTID,
    storageBucket: process.env.STORAGEBUCKET,
    messagingSenderId: process.env.MESSAGINGSENDERID,
  });
}

export default firebase;

設定ファイルに plugin を追加するのを忘れずに。

nuxt.config.js:

require("dotenv").config();

export default {
  //...

  plugins: ["~/plugins/firebase"],

  //...
};

ログインデータを永続化させる

/middleware でログイン状態をチェック

ログインデータの有無をチェックするのは middleware で行うのが一般的なようです。 onAuthStateChanged で user が戻ってきた場合にはここから store にデータを格納するのが良さそう。

user のオブジェクトをそのまま store に渡すとエラーになるので、一度const { uid, email, displayName, photoURL } = user;みたいな感じで必要なものだけバラして渡すようにしましょう。

/middleware/auth.js:

import firebase from "@/plugins/firebase";

export default function ({ store, route, redirect }) {
  if (store.state.auth.user && store.state.auth.user.uid !== undefined) return;

  firebase.auth().onAuthStateChanged((user) => {
    if (user) {
      const { uid, email, displayName, photoURL } = user;
      store.commit("auth/add", { uid, email, displayName, photoURL });
    } else {
      if (route.name !== "login") {
        redirect("/login");
      }
    }
  });
}

サイト内のどのページでもログイン状態の確認をしたい場合には設定ファイルにmiddlewareを追記します。

nuxt.config.js:

export default {
  //...

  router: {
    middleware: "auth",
  },
};

特定のページだけチェックしたい場合には個別に書いても。

/pages/index.vue:

export default {
  middleware: ["auth"],

  //...
};

/store で認証情報を取得・保存・削除

ストアに認証情報を保存したり読みに行ったり消したりする処理を記載します。 mutation の add には middleware から送られてきた値を受け取って格納するようにします。

/store/auth.js:

import firebase from "@/plugins/firebase";

const namespaced = true;

const state = () => ({
  user: {},
});

const mutations = {
  add(state, { uid, email, displayName, photoURL }) {
    state.user = {
      ...state.user,
      ...{
        uid: uid,
        email: email,
        displayName: displayName,
        photoURL: photoURL,
      },
    };
  },

  remove(state) {
    state.user = null;
  },
};

const actions = {
  async login() {
    const provider = new firebase.auth.GoogleAuthProvider();
    return await firebase.auth().signInWithRedirect(provider);
  },

  async logout({ commit }) {
    commit("remove");
    return await firebase.auth().signOut();
  },
};

export default {
  namespaced,
  state,
  mutations,
  actions,
};

login と logout のメソッドはこんな感じで呼びます。

async this.$store.dispatch("auth/login");
async this.$store.dispatch("auth/logout");

/plugin で vuex-persistedstate を使って認証状態を永続化

ここまでやるば、Vuex がストアの情報を良いようにしてくれるんですが、localStrageとかCookieにデータを保存して永続化をしておきたい場合には vuex-persistedstate の設定をします。

/plugin/persistedstate.js:

import createPersistedState from "vuex-persistedstate";

export default ({ store, isHMR }) => {
  if (isHMR) return;

  window.onNuxtReady((nuxt) => {
    createPersistedState({
      key: "xxxx",
      paths: ["auth"],
    })(store);
  });
};

key の指定はしなくても大丈夫だけどlocalhost:3000 で色々ぶつかるので指定した方が良さそう。

設定ファイルに plugin を追加。

nuxt.config.js:

export default {
  //...

  plugins: ["~/plugins/firebase", { src: "~/plugins/persistedstate.js", ssr: false }],

  //...
};

確認方法

ちゃんとローカルストレージに保存されているか確認しようと思ったら Chrome なら開発ツールの Applicatin -> Strage -> Local Strage -> http://localhost:3000/ で確認する事ができます。


こんな感じで良いのだろうか… なんか間違ってたら教えていただけると助かります。

Profile
😛

石原 悠 / Yu Ishihara

デザインとプログラミングとヨーグルト作りが好きです。