Web制作・プログラミング関連のおすすめレビュー記事はこちら

【Vue.js×Firebase】SPAでログイン機能を実装する方法を解説

Vue.js

今回はVue.jsとFirebaseを使ったSPA(Single Page Application)でログイン機能(認証機能)を作る方法を解説します。

今回は「とりあえずVue×firebaseで認証機能を実装して動かしたい」という方向けに、画像多めで分かりやすいように解説しています。

今回つける機能は以下の3つのみです。

  • 新規登録
  • ログイン
  • ログアウト

以上3つの機能だけの小さなWebアプリを作っていきます。

今回は認証機能に絞った解説なので、他にWebアプリとしての機能は実装せず、簡単なページを表示するだけとします。

かな〜り長い道のりですが、頑張っていきましょう。

Firebaseってなに?

そもそもFirebaseとは何か?を簡単に紹介します。

Firebase は Google が提供しているモバイルおよび Web アプリケーションのバックエンドサービスです。クラウドサービスの形態では BaaS に位置付けされます。 Firebase を使うことで、開発者はアプリケーションの開発に専念でき、バックエンドで動くサービスを作成する必要も管理する必要もありません。

TOPGATEより引用

いわゆるBaaS(Backend as a Service)というもので、バックエンドの構築をFirebaseにまかせて素早くWebアプリなどを構築・開発することが可能になるということですね。

Firebaseは色々な機能を提供していますが、今回は以下の1つの機能だけを使います。

  • Firebase Authentication

今回はこちらを使って、シンプルに認証機能だけのWebアプリを実装します。

Firebase SDKとREST APIについて

FirebaseにはFirebaseSDKと呼ばれる開発者用の便利な機能がパッケージングされたキットがあります。

Firebase SDK は、Cloud Firestore と他のいくつかの Firebase プロダクト(Firebase Auth や Firebase Cloud Messaging など)へのアクセスを単一のライブラリにまとめたものです。

しかし、今回はあえてこちらを使わずに、Firebase REST APIというものを使います。

REST APIを使うことで今後firebaseだけでなく、他のバックエンド言語にも応用が効く知識をつけられるためです。

REST API自体の解説はここでは行いませんが、以下の記事を読んでおくと理解が深まると思います。

0からREST APIについて調べてみた - Qiita
REST APIの概要 ★REST APIとは RESTful API(REST API)とは、Webシステムを外部から利用するためのプログラムの呼び出し規約(API)の種類の一つで、RESTと呼ばれる設計原則に従って策定...

以下ここまでのまとめです。

ここまでのまとめ
・Firebaseは色々な機能を提供するBaaSである
・今回使うのは認証機能のFirebase Authentication
・Firebase SDKではなく、Firebase REST APIを使う

Vue.jsの環境構築

まずはVue.jsの環境構築からやっていきましょう。

VueCLIで環境構築

VueCLIを使うことでVueの開発環境を簡単に構築することができます。

環境構築方法に関しては別記事でまとめていますので、以下の記事を参考にしてください。

数十分で簡単にVue, Vuex, Vue-Routerの開発環境が揃うように解説しています。

以降ディレクトリ構造やVuex,VueRouterのインストール状況などは、上の記事に沿って解説していきます。

※自分で環境を用意している方は適宜ファイル名やディレクトリ構造は読み替えてください。

拡張機能 Vue Devtoolsのインストール

今回はブラウザはChromeを使用しますが、Vueの開発を行う上で便利な拡張機能があるのでインストールします。

Googleで「Vue Devtools」と調べてインストールし、有効化しておいてください。

こちらを有効化した状態で検証ツールを開いてみると、consoleなどが並んでるバーの一番右にVueという項目が追加されてますね。

Vueタブの中ではコンポーネント、Vuex、イベント、VueRouterの情報などが確認できます。

以下ここまでのまとめです。

ここまでのまとめ
・VueCLIでVueの環境構築をした
・Vue DevtoolsというChromeの拡張機能をインストールした

SPA上でのログイン機能の仕組み

次にSPA上でのログイン機能を仕組みについて確認します。

サーバーにログイン情報を渡すと、トークン(=本人確認用の文字列)が返ってきます。

以降は自分が持っているトークンとサーバーに保存されているトークンが合致すれば、色々とリクエストができるという仕組みになります。

以下ここまでのまとめです。

ここまでのまとめ
・ログイン情報を渡すとサーバーはトークンを返す
・トークンを照合することで認証機能を実装する

各種ページを実装する

このセクションでは今回のWebアプリで使用する4つのページを作成し、VueRouterで登録・表示するところまでやっていきます。

ページ用のVueコンポーネントを作成

今回作成するのは以下の4つのページです。

  • トップページ
  • 詳細ページ(ログイン必須)
  • ログインページ
  • 新規登録ページ

まずは/srcディレクトリ直下にpagesディレクトリを作成します。

その中にHome.vue, About.vue, Login.vue, Register.vueの4つのファイルを作成してください。

それぞれの内容は今回は以下のようにしました。

<template>
<div class="container">
  <h2>Topページです</h2>
</div>
</template>
<template>
  <div class="container">
    <h2>詳細ページです</h2>
    <p>ログインが必要なページです</p>
  </div>
</template>
<template>
<div class="container">
  <h2>ログイン</h2>
  <form class="login-form">
    <div class="input-group">
      <label for="email">メールアドレス</label>
      <input type="email" id="email">
    </div>
    <div class="input-group">
      <label for="password">パスワード</label>
      <input type="password" id="password">
    </div>
    <div class="input-group">
      <button type="button">送信</button>
    </div>
  </form>
</div>
</template>

<style>
.input-group {
  margin: 5px;
}
</style>
<template>
<div class="container">
  <h2>新規登録</h2>
  <form class="login-form">
    <div class="input-group">
      <label for="email">メールアドレス</label>
      <input type="email" id="email">
    </div>
    <div class="input-group">
      <label for="password">パスワード</label>
      <input type="password" id="password">
    </div>
    <div class="input-group">
      <button type="button">新規登録</button>
    </div>
  </form>
</div>
</template>

ほとんどHTML&CSSなのでコピペしてOKです。

VueRouterでページを登録する

次にVueRouterを使って作成したページコンポーネントを登録していきます。

router.jsで以下のように登録します。

import Vue from 'vue';
import Router from 'vue-router';
import Home from './pages/Home.vue';
import About from './pages/About.vue';
import Login from './pages/Login.vue';
import Register from './pages/Register.vue';

Vue.use(Router);

export default new Router({
  mode: "history",
  routes: [
    { path: '/', component: Home },
    { path: '/about', component: About },
    { path: '/login', component: Login },
    { path: '/register', component: Register },
  ]
});

作成したHome.vue, About.vue, Login.vue, Register.vueの4つを登録しました。

App.vueでページの表示とメニューの実装

次に、App.vueを編集し、各ページに飛べるようにメニューを実装します。

また、<router-view></router-view>を記述してページを表示できるようにします。

<template>
  <div>
    <header class="header">
      <router-link to="/" class="header--link">トップ</router-link>
      <router-link to="/about" class="header--link">詳細</router-link>
      <router-link to="/login" class="header--link">ログイン</router-link>
      <router-link to="/register" class="header--link">新規登録</router-link>
    </header>
    <router-view></router-view> 
  </div>
</template>

<style scoped>
.header {
  text-align: center;
  display: flex;
  justify-content: center;
}
.header--link {
  padding: 10px;
}
</style>

以下のようにページを表示と切り替えができていればOKです。

Home.vue
About.vue
Login.vue
Register.vue

以下、このステップのまとめです。

ここまでのまとめ
・src/pagesフォルダに4つのページコンポーネントを作成した
・VueRouterのrouter.jsでパスとページを登録した
・App.vueでメニューを作成し、各種ページを表示できるようにした

Firebase側の設定

このステップでは、Firebaseのプロジェクトの作成とFirebase Authenticationの設定を行っていきます。

Firebaseプロジェクトの作成

初めに、Firebaseのプロジェクトを作成していきます。

まずは「Firebase」と調べて一番上に出てくるサイトをクリックしてログインします。

トップページが表示されたら「使ってみる」をクリック。

プロジェクトを追加をクリック。

プロジェクトの名前を決めます。

今回は「vue-login-practice」とします。

Googleアナリティクスの設定を聞かれますが、今回は練習なので「なし」でOKでしょう。

プロジェクトの作成が始まって、、

完了しました。

青い「続行」ボタンをクリックします。

プロジェクトの一覧画面に戻ると、先程作った「vue-login-practice」があるのが分かりますね。

Firebase Authenticationの設定

次は認証機能の核となるFirebase Authenticationの設定を行っていきます。

プロジェクト一覧から、作成したプロジェクトをクリックして、

プロジェクト毎のトップページを開きます。

左のメニューバーから「Authentication」をクリック。

上のタブバーで「Sign-in method」を選んだら、一番上の「メール/パスワード」を選択します。

有効にするかどうかのボタンが2つ出るので上のものだけを有効にします。

保存をクリックして終了。

これでFirebase Authenticationの設定は完了です。簡単ですね。

以下ここまでのまとめです。

ここまでのまとめ
・Firebaseの新規プロジェクトを作成した
・Firebase Authenticationで「メール/パスワード」での登録を有効にした

新規登録機能の実装

いよいよユーザーの新規登録の機能を実装していきます。

今回は一番初めにもお話したとおり、Firebase REST APIを使ってサーバーへのリクエストを行います。

そのためこのステップでは、サーバーとHTTP通信を行うためのライブラリ「axios」のインストールと、実際に新規登録のフォームを機能するように実装していきます。

Firebase REST APIのドキュメントを確認

まずはGoogleで「Firebase Auth REST API」と検索してみましょう。

一番上の公式ドキュメントが出てくるので、開いたら右側の目次から「Sign up with email / password」をクリックします。

Firebase Auth REST APIの公式ドキュメント

まずは、注目するべきなのは「EndPoind」と書かれた以下のURLです。

https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=[API_KEY]

エンドポイントは、簡単に説明するとAPIへリクエストを送るためのURLです。

しかし、APIを使うユーザーが全員同じAPIのURLにリクエストを送るわけにはいきません。

セキュリティや利用条件などをある程度担保する必要があるため、そこで使われるのがAPIキーという仕組みです。

このAPIキーを知っている人だけがAPIへアクセスできるようにすることで、利用に制限を掛けているという訳ですね。(なので自分のAPIキーは基本的に公開してはいけません。)

次は、FirebaseプロジェクトのAPIキーを確認するステップに移りましょう。

FirebaseプロジェクトのAPIキーを確認する

まずはプロジェクトのトップ画面から、左側の歯車マークをクリックし、「プロジェクトを設定」を選択。

そこで出てくる「ウェブAPIキー」があなたのプロジェクトのAPIキーです。

これをコピーします。

ドキュメントで確認したURLをもう一度見てみます。

https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=[API_KEY]

末尾にkey=[API_KEY]という記述があるので、そこに自分のAPIキーをペーストします。
([ ]も消してOKです。)

最終的にできた以下のようなURLが、あなたのFirebase Authenticationへアクセスするためのエンドポイントです。後で使うので控えておいてください。

https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=yourAPIkey

axiosのインストールとインスタンスの作成

JavaScriptの標準の機能でもサーバーへの通信はできるのですが、今回はいろいろと便利な機能のある「axios」というライブラリを使って実装していきます。

まずはnpmでaxiosをインストールしましょう。

ターミナルでVueプロジェクトのディレクトリまで移動して、

$ cd vue-for-blog

開発環境にaxiosをインストールします。

$ npm install -D axios

Vueプロジェクトフォルダ直下のpackage.jsonを確認して、devDependenciesの中にaxiosがあれば正常にインストールできています。

  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.4.0",
    "@vue/cli-plugin-eslint": "~4.4.0",
    "@vue/cli-service": "~4.4.0",
    "axios": "^0.19.2", //axiosがあることを確認
    "babel-eslint": "^10.1.0",
    "eslint": "^6.7.2",
    "eslint-plugin-vue": "^6.2.2",
    "vue-template-compiler": "^2.6.11"
  },

次はaxiosのインスタンスを作成していきます。

/srcディレクトリ直下にaxios-for-auth.jsという新しいファイルを作成します。

以下のコードではaxiosのインスタンスを作成し、baseURLに先程確認したエンドポイントの途中まで("/v1"まで)を設定しておきます。

import axios from 'axios';

const instance = axios.create({
  baseURL: 'https://identitytoolkit.googleapis.com/v1'

});

export default instance;

後ほど、このインスタンスをimportして使うと、アクセスするURLの頭に設定したbaseURLがくっつくようになります。

Register.vueを編集してフォームを実装

次は、Register.vueを編集して実際にREST APIへのアクセスをしてみましょう。

ここでもう一度ドキュメントを確認します。

「Request Body Payload」を確認すると、以下のような記述があります。

Property NameTypeDescription
emailstringThe email for the user to create.
passwordstringThe password for the user to create.
returnSecureTokenbooleanWhether or not to return an ID and refresh token. Should always be true.

"email"と"password"は新規作成したいユーザーのもの、"returnSecureToken"は常にtrueを送ってください、と書いてありますね。

ここまでの情報をまとめると、以前確認したエンドポイントにemail, password, returnSecreTokenを送ることで新規ユーザー登録ができるということになります。

これを元に、Register.vueを以下のように編集しました。(追記部分はコメントつけてます。)

<template>
<div class="container">
  <h2>新規登録</h2>
  <form class="login-form">
    <div class="input-group">
      <label for="email">メールアドレス</label>
      <input type="email" id="email" v-model="email"> //v-modelで結びつける
    </div>
    <div class="input-group">
      <label for="password">パスワード</label>
      <input type="password" id="password" v-model="password"> //v-modelで結びつける
    </div>
    <div class="input-group">
      <button type="button" @click="register()">新規登録</button> //クリックしたらregister()発火
    </div>
  </form>
</div>
</template>

<script> 
import axios from '../axios-for-auth.js'; //axiosのインスタンスをインポート
export default {
  data() {
    return {
      email: "",
      password: ""
    }
  },
  methods: {
    register() { //axiosでapiを叩くメソッドを定義
      axios.post(
        '/accounts:signUp?key=yourAPIkey',
        {
          email: this.email,
          password: this.password,
          returnSecureToken: true
        } 
      ).then((response) => { 
        console.log(response); //返ってきたレスポンスをログに表示
      });
      this.email = "";
      this.password = "";
    }
  }
}
</script>

主に新しくやっていることは以下のとおりです。

  • v-modelでemailとpasswordそれぞれを結びつける
  • 作成したaxiosのインスタンスをimportする
  • axiosでエンドポイントにアクセスするregisterメソッドを定義
    (postで送るべき情報はドキュメント参照)
  • ボタンを押したらregisterメソッドを発火

v-modelでemailとpasswordをそれぞれ結びつけて、returnSecureToken: trueと一緒にエンドポイントに送ります。

axiosのpostメソッドの第一引数が"/accounts:signUp?key=yourAPIkey"となっていますが、importしているaxiosインスタンスのbaseURLが頭にくっつくので、結果としてリクエストの送信先は前に確認した以下のURLという訳ですね。

https://identitytoolkit.googleapis.com/v1/accounts:signUp?key=yourAPIkey

動作確認

ここまでできたら動作確認をしてみましょう。

新規登録フォームで適当なメールアドレスとパスワードを入力して送信。

検証ツールのconsoleを確認して、しっかりレスポンスが返ってきていれば成功です。

入力したメールアドレスや、トークンが返ってきているのが分かります。

コンソールでエラーが出る場合はエンドポイントのURLなどが間違っていないか確認しましょう。

次に、Firebase Authentication側の画面も確認してみましょう。

Firebase Authenticationのページで入力したユーザーが作成されていれば成功です。

これで新規登録機能の実装は完了です。お疲れさまでした。

以下ここまでのまとめです。

ここまでのまとめ
・自分のAPIキーを確認し、エンドポイントのURLに反映させた
・axiosをインストールして、新しいインスタンスを作成した
・新規登録フォームの情報をaxiosを使ってエンドポイントに送信した
・consoleで正常にレスポンスが返ってきていることを確認した

ログイン機能の実装

ここからはログイン機能の実装に入ります。

新規登録とほとんど同じなので、どんどん行きましょう。

Firebase REST APIのドキュメントを確認

まずはドキュメントの確認からです。

Firebase Auth REST API」のドキュメントのページから、右の目次の「SIgn in with email / password」をクリック。

同じようにエンドポイントを確認します。

https://identitytoolkit.googleapis.com/v1/accounts:signInWithPassword?key=[API_KEY]

新規登録とは最後の方が微妙に異なりますね。こちらも 同じように自分のAPIキーをURL内に貼り付けて利用してください。

ただ、axiosのインスタンスのbaseURLにhttps://identitytoolkit.googleapis.com/v1は登録してあるので、実際に使うのは以下の部分になります。

/accounts:signInWithPassword?key=yourAPIkey

こちらを後で使うので控えておきましょう。

Login.vueを編集してフォームを実装

次は、Login.vueを編集して実際にREST APIへのアクセスをしてみましょう。

ログインの場合もドキュメントの「Request Body Payload」を確認すると、以下のような記述があります。

Property NameTypeDescription
emailstringThe email for the user to create.
passwordstringThe password for the user to create.
returnSecureTokenbooleanWhether or not to return an ID and refresh token. Should always be true.

新規登録と全く同じですね。

これを元に、Login.vueを以下のように編集しました。(追記部分はコメントつけてます。)

<template>
<div class="container">
  <h2>ログイン</h2>
  <form class="login-form">
    <div class="input-group">
      <label for="email">メールアドレス</label>
      <input type="email" id="email" v-model="email"> //v-modelで結びつける
    </div>
    <div class="input-group">
      <label for="password">パスワード</label>
      <input type="password" id="password" v-model="password"> //v-modelで結びつける
    </div>
    <div class="input-group">
      <button type="button" @click="login()">送信</button> //クリックしたらlogin()を発火
    </div>
  </form>
</div>
</template>

<script>
import axios from '../axios-for-auth.js'; //axiosのインスタンスをインポート
export default {
  data() {
    return {
      email: "",
      password: ""
    }
  }, 
  methods: {
    login() { //axiosでログイン用のインスタンスにアクセスするメソッドを定義
      axios.post( //エンドポイントのURLがログイン用のものを使う
        '/accounts:signInWithPassword?key=AIzaSyD4fPRWu_O2Cpp_Rb9mJ1oziq-0VILpqBI',
        {
          email: this.email, //送る情報は新規登録と同じ
          password: this.password,
          returnSecureToken: true
        }
      ).then((response) => {
        console.log(response); //返ってきたレスポンスをログに表示
      });
      this.email = "";
      this.password = "";
    }
  }
}
</script>

<style>
.input-group {
  margin: 5px;
}
</style>

やっていることは以下の通りで、ほとんど 新規登録の場合と同じです。

  • v-modelでemailとpasswordそれぞれを結びつける
  • 作成したaxiosのインスタンスをimportする
  • axiosでエンドポイントにアクセスするloginメソッドを定義
    (postで送る情報は新規登録のときと同じ)
  • ログイン用のエンドポイントに送るように変更
  • ボタンを押したらloginメソッドを発火

動作確認

ここまで来たら動作確認です。

先程新規登録したメールアドレスとパスワードの組み合わせでログインフォームから送信すると、

コンソールにレスポンスが返ってきていれば成功です。

入力したメールアドレスや、トークンなど色々な情報が返ってきているのが分かります。

これでログイン機能の実装は完了です。お疲れさまでした。

以下ここまでのまとめです。

ここまでのまとめ
・新規登録とはエンドポイントが異なることに注意する
・自分のAPIキーを確認し、エンドポイントのURLに反映させた
・ログインフォームの情報をaxiosを使ってエンドポイントに送信した
・consoleで正常にレスポンスが返ってきていることを確認した

Vuexでトークンを状態管理する

今まで、新規登録やログインした時にレスポンスとしてidTokenが返ってきているのを確認しました。

これをVuexを使って状態管理することで今回のWebアプリ全体で使えるようにしていきます。

Vuexのインストールとセットアップ

まずはnpmでVuexをインストールします。(Vuexインストール済みの方は飛ばしてください。)

npm install vuex

次に/srcディレクトリ内にstoreディレクトリを作成し、その中にindex.jsというファイルを作成し、以下のように編集します。

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
});

次に、main.jsでVuexを使うように登録します。

import Vue from 'vue'
import App from './App.vue'
import router from './router';
import store from  './store' //追記

Vue.config.productionTip = false

new Vue({
  router,
  store, //追記
  render: h => h(App),
}).$mount('#app')

これでVuexを使う準備はできました。

idTokenを状態管理する

先程作成したstore/index.jsを以下のように編集します。

import Vue from 'vue';
import Vuex from 'vuex';

Vue.use(Vuex);

export default new Vuex.Store({
  state: {
    idToken: null
  }, 
  getters: {
    idToken: state => state.idToken
  },
  mutations: {
    updateIdToken(state, idToken) { 
      state.idToken = idToken;
    }
  },
});

stateとしてidTokenを初期値nullで定義し、mutationsでidTokenを渡された値で更新するように定義しました。

gettersは後で色々なファイルからstateを参照できるように、単純にstateの状態を返すように定義しています。

後はこのmutationsをLogin.vueとRegister.vueで呼び出せるようにしていきます。

loginメソッドとregisterメソッドを以下のように編集します。
(追記部分はコメントつけてます。)

<script>
import axios from '../axios-for-auth.js';
export default {
  data() {
    return {
      email: "",
      password: ""
    }
  }, 
  methods: {
    login() {
      axios.post(
        '/accounts:signInWithPassword?key=AIzaSyD4fPRWu_O2Cpp_Rb9mJ1oziq-0VILpqBI',
        {
          email: this.email,
          password: this.password,
          returnSecureToken: true
        }
      ).then((response) => {
        this.$store.commit('updateIdToken', response.data.idToken) //追記
     this.$router.push('/');  //追記
      });
      this.email = "";
      this.password = "";
    }
  }
}
</script>
<script>
import axios from '../axios-for-auth.js';
export default {
  data() {
    return {
      email: "",
      password: ""
    }
  },
  methods: {
    register() {
      axios.post(
        '/accounts:signUp?key=AIzaSyD4fPRWu_O2Cpp_Rb9mJ1oziq-0VILpqBI',
        {
          email: this.email,
          password: this.password,
          returnSecureToken: true
        }
      ).then((response) => {
        this.$store.commit('updateIdToken', response.data.idToken); //追記
     this.$router.push('/');  //追記
      });
      this.email = "";
      this.password = "";
    }
  }
}
</script>

どちらも受け取ったレスポンスのidTokenをVuexのupdateIdTokenに渡しています。

ついでにログインや新規登録が正常に終わったら、ホーム画面("/")に戻るようにしました。

動作確認

ここまで実装できたらVueDevToolを使って動作確認をします。

登録済みのメールアドレスとパスワードでログインして、Vue DevtoolsのidTokenを確認してみてください。

画像のように、長い文字列がidTokenとしてstateに入っていればOKです。

同じように新規登録をした際にもidTokenが入っていることを確認してください。

ログインの有無で処理を変更する

前回まででログインと新規登録の処理は実装できました。

しかし、現状のままではログインしていない状態でも全てのページにアクセスできます。

さらに、ヘッダーメニューもログイン状態に関係なく、全てのリンクが表示されています。

これらの問題を解決していきましょう。

ナビゲーションガードでリダイレクト処理

今回は詳細ページ(/about)はログインしていないと見れないように設定したいので、ログイン状態の有無でアクセスに制限をかけるということをやっていきましょう。

使うのはVueの標準機能のナビゲーションガードという機能です。

ざっくり説明すると、URLへアクセスする直前などのタイミングで特定の処理を自動的に行うというものです。

ナビゲーションガード | Vue Router
Vue.js の公式ルータ

こちらを利用してログインしていない状態で"/about"にアクセスしようとしたら、"/login"に飛ばす。既にログインしている状態で、"/login"や"/register"にアクセスしようとすると、"/"に飛ばすという処理を書いていきます。

その処理をrouter.jsに書くと以下のようになります。(追記部分はコメントをつけています。)

import Vue from 'vue';
import Router from 'vue-router';
import Home from './pages/Home.vue';
import About from './pages/About.vue';
import Login from './pages/Login.vue';
import Register from './pages/Register.vue';
import store from './store'; //追記

Vue.use(Router);

export default new Router({
  mode: "history",
  routes: [
    {
      path: "/",
      component: Home,
    },
    {
      path: "/about",
      component: About,
      beforeEnter(to, from, next) { //追記
        if (store.getters.idToken) { //idTokenがあれば、そのまま"/about"に
          next();
        } else { //なければ"/login"に飛ばす
          next("/login");
        }
      },
    },
    {
      path: "/login",
      component: Login,
      beforeEnter(to, from, next) { //追記
        if (store.getters.idToken) { //すでにidTokenがあれば、"/"に飛ばす
          next("/");
        } else { //なければそのまま"/login"に
          next();
        }
      },
    },
    {
      path: "/register",
      component: Register, 
      beforeEnter(to, from, next) { //追記
        if (store.getters.idToken) { //すでにidTokenがあれば、"/"に飛ばす
          next("/");
        } else { //なければそのまま"/register"に
          next();
        }
      },
    },
  ],
});

これでログイン状態、非ログイン状態で動作確認してみましょう。

以下2点が確認できればOKです。

  • ログインしていない状態で、"/about"にアクセスできない。
  • ログインしている状態で、"/login"と"/register"にアクセスできない。

ログインの有無でUIを変える

ログイン状態の有無でアクセスに制限をかけることができました。

しかし、現状ではヘッダーメニューに、場合によってアクセスできないリンクが残っているのが気になりますね。

これをログインの有無で出し分けていきます。

App.vueを以下のように編集しましょう。

<template>
  <div>
    <header class="header">
      <router-link to="/" class="header--link">トップ</router-link>
      <router-link to="/about" class="header--link" v-if="isLoggedIn">詳細</router-link>
      <router-link to="/login" class="header--link" v-if="!isLoggedIn">ログイン</router-link>
      <router-link to="/register" class="header--link" v-if="!isLoggedIn">新規登録</router-link>
    </header>
    <router-view></router-view> 
  </div>
</template>

<script>
export default {
  computed: {
    isLoggedIn() {
      return this.$store.getters.idToken !== null;
    }
  }
}
</script>

新しく、isLoggedInというcomputedを定義しました。

これはVuexのstateを参照し、idTokenがnullではない時(ログインしている時)にtrueを返します。これを使ってv-ifでヘッダーメニューのリンクを出し分けています。

ログアウト機能の実装

最後にログアウト機能を実装していきましょう。

ログアウト用のボタンとメソッドを作成

まずはAbout.vueを以下のように編集して、ログアウト用のボタンを追加しましょう。

<template>
  <div class="container">
    <h2>詳細ページです</h2>
    <p>ログインが必要なページです</p>
    <button type="button" @click="logout()">ログアウトする</button>
  </div>
</template>

<script>
export default {
  methods: {
    logout() {
      this.$store.commit('updateIdToken', null);
      this.$router.push('/login');
    }
  }
}
</script>

クリックしたらlogoutメソッドを発火しています。

logoutメソッドではVuexストアのidTokenをnullにすることでログアウトを実現しています。

また、vue-routerを使ってログアウト後に自動でログインページに飛ぶようにしています。

ログアウト機能はこれで完成です。

動作確認

最後に動作確認をしてみましょう。

まずはログインして、

詳細ページを表示します。

ログアウトするをクリックして、正常にログインページ移動できたら成功です。

念の為、トークンがなくなっていることも確認しておきましょう。

VueDevtoolでVuexを確認して、stateのidTokenがnullになっていることが確認できればOKです。

ここまでで新規登録・ログイン・ログアウト機能のすべてを実装できました。お疲れさまでした。

最後に

今回はfirebaseとvue.jsでログイン機能を作る方法を解説しました。

実は今回の機能は、ブラウザの更新ボタンを押すとログイン機能が保持できないので、リフレッシュトークンというものを使ってログイン状態の保持を実装してみると勉強になると思います。

Vue.jsは色々な機能を手軽に試せるのが魅力なので、是非色々とチャレンジしてみてください。

それでは、今回は以上です。

Vue.jsの人気記事はこちら
タイトルとURLをコピーしました