🔑 Nuxt.js + Firebase Authentication

2020-11-26 /Development
この記事は最終更新日から2年以上経過しています。

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/ で確認する事ができます。


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

Comment
comments powered by Disqus
Profile

石原 悠 / Yu Ishihara

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