LoginSignup
4
1

More than 3 years have passed since last update.

【Firebase Authentication】Nuxt.jsで作成したアプリケーションにログイン機能をつける。

Posted at

Nuxt.jsでのログイン実装

現在ユーザー機能が必要なアプリケーションを作成しているため,ログイン機能を実装する必要があります。
Firebase Authenticationの機能を使って登録したユーザーがログインできるかを確認します。

前提

・Firebaseが使える状態にある
・axiosがインストール済みである

ページ構成

よくあるヘッダーの右側にログイン、サインインがあるパターンを想定します。
こんな感じです。

まずはリンク先のページをpages配下に用意してあげましょう。


touch pages/login.vue

続いてヘッダーにリンクを用意してあげましょう。
Nuxtはルーティングが簡単にできるからとても便利ですね。

header.vue
<ul class="list-inline">
  <li class="list-inline-item"><n-link to="/login">Log in</n-link></li>
</ul>

loginフォームを用意する

シンプルなフォームがほしかったためこちらからお借りしました。

Firebase Authenticationでユーザーを用意

1.Authenticationをクリック
2.ユーザーを追加をクリック
3.メールアドレスとパスワードを入力(存在しないもので構いません)
4.ユーザーを追加をクリック

Sign-in methodの設定

1.Sign-in methodをクリック
2.メール/パスワードを有効化

plugins/firebase.jsを用意

firebaseの情報を設定します。
1.プロジェクトの概要 > 歯車をクリック > プロジェクトを設定をクリック
2.全般をスクロールする

こちらの画面をスクロールすると表示される情報ですね。

plugins/firebase.js

const config = {
  apiKey: "{{ APIKEY }}",
  authDomain: "{{ AUTHDOMAIN }}",
  databaseURL: "{{ DATABASEURL }}",
  projectId: "{{ PROJECTID }}",
  storageBucket: "{{ STORAGEBUCKET }}",
  messagingSenderId: "{{ MESSAGINGSENDERID }}",
  appId: "{{ APPID }}",
  measurementId: "{{ MESUREMENTID }}"
};

// Initialize Firebase
if (!firebase.apps.length) {
  firebase.initializeApp(config);
}

export default firebase;

storeを用意する

データを保存しておくという仕組みしか理解しておりませんので、提供いただいたコードをそのまま掲載します。

store/index.js
import firebase from '~/plugins/firebase'

// data保管庫
export const state = () => ({
  user: {
    uid: '',
    email: '',
    login: false,
  },
})

// stateの情報を取得
export const getters = {
  user: state => {
    return state.user;
  }
}

// storeの上書き以外の処理や非同期通信
export const actions = {
  login({ dispatch }, payload) {
    // メールとパスワードでログイン
    console.log('login action');
    firebase.auth().signInWithEmailAndPassword(payload.email, payload.password)
      .then(user => {
        console.log('ログイン成功!');
        this.$router.replace({ path: '/' });
        dispatch('checkLogin')
      })
      .catch((error) => {
        alert(error);
      })
  },
  loginGoogle({ dispatch }) {
    // Googleアカウントでログイン
    console.log('loginGoogle action');
    const provider = new firebase.auth.GoogleAuthProvider();
    firebase.auth().signInWithPopup(provider)
      .then(result => {
        const user = result.user;
        console.log('googleログイン成功!');

        dispatch('checkLogin');
      })
      .catch((error) => {
        alert(error);
      });
  },
  checkLogin({ commit }) {
    // ログインしているかどうかのチェックログインしていたらデータ追加
    firebase.auth().onAuthStateChanged((user) => {
      console.log(user);
      if (user) {
        console.log(user);
        commit('login', { uid: user.uid, email: user.email });
      }
    })
  },
  logout({ commit }) {
    // ログアウト
    firebase.auth().signOut()
      .then(() => {
        console.log("ログアウトしました");
        commit('logout');
      })
      .catch((error) => {
        console.log(`ログアウト時にエラーが発生しました (${error})`);
      });
  }
}

// stateの上書き(代入)
export const mutations = {
  login(state, payload) {
    state.user.uid = payload.uid;
    state.user.email = payload.email;
    state.user.login = true;
  },
  logout(state) {
    state.user.uid = '';
    state.user.email = '';
    state.user.login = false;
  }
}

ここまでで下準備が終わりました

login.vueから実処理を行うLoginMenuのコンポーネントを呼び出します

pages/login.vue
<template>
    <div>
      <h1>Log In</h1>
      <LoginMenu />
      <h3 v-if="user.login">
       ログインしました
      </h3>
      <h3 class="title" v-else>
       ログインしてください
      </h3>
    </div>
</template>

<script>
  import LoginMenu from "@/components/loginMenu.vue";
  export default {
    components: {
      LoginMenu: LoginMenu,
    },
    computed: {
        user() {
          return this.$store.getters["user"];
        },
    }
  };
</script>

components/loginMenu.vue
<template>
<div class="login-page">
  <div class="form">
    <div class="register-form" v-if="this.$route.path === '/signup'">
      <input type="text" placeholder="name"/>
      <input type="password" placeholder="password"/>
      <input type="text" placeholder="email address"/>
      <button>create</button>
      <p class="message">Already registered? <n-link to="/login">Sign In</n-link></p>
    </div>
    <div class="login-form" v-else>
      <input type="text" v-model="email" placeholder="username"/>
      <input type="password" v-model="password" placeholder="password"/>
      <button v-on:click="login">login</button>
      <p class="message">Not registered? <n-link to="/signup">Create an account</n-link></p>
    </div>
  </div>
</div>
</template>

<script>
export default {
 computed: {
   // dataのように扱える
   // dataを作る前処理が必要な際に利用
   user () {
     return this.$store.getters['user'];
   },
 },
 data () {
   return {
     email: '',
     password: '',
   }
 },
 mounted() {
   // ログインしているかどうかのチェックログインしていたらデータ追加
   this.$store.dispatch('checkLogin');
 },
 methods : {
   async login () {
      // メールとパスワードでログイン
      console.log('login action', this.email, this.password);
      this.$store.dispatch('login', {email:this.email, password:this.password});
   },
   loginGoogle() {
      // Googleアカウントでログイン
      this.$store.dispatch('loginGoogle');
   },
   logout : function() {
      // ログアウト
      this.$store.dispatch('logout');
   }
 }
}
</script>

ログイン可能か確認する

ひとまずログインを行うと右のメニューがlogoutになるか確認します。

header.vue
<template>
    <nav class="navbar navbar-light bg-light">
        <h1><n-link to="/">title</n-link></h1>
        <ul class="list-inline" v-if="user.login">
            <li class="list-inline-item"><n-link to="/logout" >Log Out</n-link></li>
        </ul>
        <ul class="list-inline" v-else>
            <li class="list-inline-item"><n-link to="/login">Log in</n-link></li>
            <li class="list-inline-item"><n-link to="/signup">Sign up</n-link></li>
       </ul>
    </nav>
</template>

ひとまず作りながら覚えていく

Nuxt.jsは以前から何度か触れていましたが複数ページにまたがる物を作るのは今回が初めてだったため
作りながら覚えていくことになります。
ひとまずstoreやstateについて早急に学んでいく必要がありますね。

4
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
1