Help us understand the problem. What is going on with this article?

FirebaseUI + vueでログイン処理

More than 1 year has passed since last update.

概要

firebaseuiとVue.jsを使ったログイン処理
一度ログインしたらログインフォームは非表示にする。(匿名ログインは除く)
匿名ログインは「ゲスト」として表示する。
匿名ログイン後、SNSアカウントでログインしたら統合させる。

環境

  • Windows10
  • Node.js v10.15.0
  • Vue.js 2.9.6
  • Firebase 6.4.0

環境構築

windowsにNode.jsをインストール

推奨版をインストール
https://nodejs.org/ja/

Node.jsのバージョン確認
https://qiita.com/strsk/items/925644e124efcc964625

> node -v
v10.15.0

npmにVue.jsインストール

> npm install -g vue-cli

> vue -V
2.9.6

Vueプロジェクトを作成

Enter5回、No3回、npmを選択してEnter

> vue init webpack memomemo

? Project name memomemo
? Project description A Vue.js project
? Author okdyy75 <xxxxx75@gmail.com>
? Vue build standalone
? Install vue-router? Yes
? Use ESLint to lint your code? No
? Set up unit tests No
? Setup e2e tests with Nightwatch? No
? Should we run `npm install` for you after the project has been created? (recommended) npm

「 To get started」の以下コマンドを実行

To get started:

  cd memomemo
  npm run dev

vue init 時に作成されたREADME

# install dependencies
npm install

# serve with hot reload at localhost:8080
npm run dev

# build for production with minification
npm run build

# build for production and view the bundle analyzer report
npm run build --report

For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).

Firebaseプロジェクトを作成

Firebaseコンソールからプロジェクトを作成
https://console.firebase.google.com/

Firebase ツールをインストール

> npm install -g firebase-tools

firebase にログインして、Firebaseプロジェクト作成

> firebase login
...

> firebase init

どのFirebase CLI機能を使うかSpaceキーを押して選択

Hostingを選択してEnter

? Which Firebase CLI features do you want to setup for this folder? Press Space to select features, then Enter to confi
rm your choices.
 ( ) Database: Deploy Firebase Realtime Database Rules
 ( ) Firestore: Deploy rules and create indexes for Firestore
 ( ) Functions: Configure and deploy Cloud Functions
>(*) Hosting: Configure and deploy Firebase Hosting sites
 ( ) Storage: Deploy Cloud Storage security rules

コンソールから作成したプロジェクトを選択

? Select a default Firebase project for this directory:
  [don't setup a default project]
> fir-84a0c (dev-firebase)
  [create a new project]
  1. Hostingの公開ディレクトリ(public)にするか聞かれているので、「dist」にしてEnter

  2. SPA(シングルページアプリケーション)として設定(すべてのURLを/index.htmlにアクセス)するか
    聞かれているので、「dist」にしてEnter

? What do you want to use as your public directory? dist
? Configure as a single-page app (rewrite all urls to /index.html)? Yes

Firebaseの初期化が完了

+  Firebase initialization complete!

firebaseがローカルで動くか確認

> firebase serve

i  hosting: Serving hosting files from: dist
+  hosting: Local server: http://localhost:5000

firebase初期画面が表示されたらOK

プロジェクトの設定

# firebaseのインストール
> npm install firebase --save

# firebase-uiのインストール
# [FirebaseUI公式リファレンス](https://github.com/firebase/firebaseui-web)
> npm install firebaseui --save

# firebase-ui日本語のインストール
> npm install firebaseui-ja --save

使用したい場所で下記のように読み込む

var firebase = require("firebase");
var firebaseui = require("firebaseui-ja");
require("firebaseui-ja/dist/firebaseui.css");

ログイン方法を有効にする

firebaseコンソールの「Authentication」の「ログイン方法」
から使用したいSNSを有効にしておく

各SNSデベロッパーサイト

以下ソース

index.html
<!DOCTYPE html>
<html>
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width,initial-scale=1.0">
    <title>FirebaseUI + vueでログイン</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- built files will be auto injected -->
  </body>
</html>

firebaseコンソールの「Authentication」の「ウェブ設定」から
下記設定を追加

/src/main.js
import Vue from 'vue'
import App from './App'
import router from './router'

Vue.config.productionTip = false

var firebase = require('firebase');
var config = {
  apiKey: "xxxxxxxxxxx",
  authDomain: "xxxx-xxxx.firebaseapp.com",
  databaseURL: "https://xxxx-xxxx.firebaseio.com",
  projectId: "xxxx-xxxx",
  storageBucket: "xxxx-xxxx.appspot.com",
  messagingSenderId: "xxxxxxxx"
};
firebase.initializeApp(config);

src/route/index.js
import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'

Vue.use(Router)

export default new Router({
  routes: [
    {
      path: '/',
      name: 'Home',
      component: Home
    }
  ]
})

src/components/Home.vue
<template>
  <div class="app">
    <h2>ログインフォーム</h2>
    <Login v-if="!isLogin || loginUser.displayName == 'ゲスト'"></Login>

    <h2>ログアウトフォーム</h2>
    <Logout v-if="isLogin" :loginUser="loginUser"></Logout>

    <div v-if="isLogin">
      <div>{{loginUser.displayName}} さん</div>
      <div>
        <img :src="loginUser.photoURL">
      </div>
      <div></div>
    </div>
  </div>
</template>


<script>
var firebase = require("firebase");
import Login from "@/components/Login.vue";
import Logout from "@/components/Logout.vue";

export default {
  name: "Index",
  components: {
    Login: Login,
    Logout: Logout
  },
  data() {
    return {
      isLogin: false,
      loginUser: null
    };
  },
  beforeRouteEnter(route, redirect, next) {
    console.log("Home_beforeRouteEnter");
    firebase.auth().onAuthStateChanged(user => {
      console.log("onAuthStateChanged", user);
      next(vm => {
        var user = firebase.auth().currentUser;

        if (!user) {
          return;
        }

        vm.isLogin = true;
        vm.loginUser = user;
      });
    });
  },
  beforeRouteUpdate(to, from, next) {
    console.log("Home_beforeRouteUpdate");
    vm.isLogin = false;
    vm.loginUser = null;
    firebase.auth().onAuthStateChanged(user => {
      console.log("onAuthStateChanged", user);
      if (!user) {
        next();
        return;
      }
      vm.isLogin = true;
      vm.loginUser = user;
      next();
    });
  }
};
</script>
src/components/Login.vue
<template>
  <div>
    <div id="firebaseui-auth-container"></div>
  </div>
</template>

<script>
var firebase = require("firebase");
var firebaseui = require("firebaseui-ja");
require("firebaseui-ja/dist/firebaseui.css");

export default {
  name: "Login",
  mounted() {
    console.log("Login_mounted");
    var vm = this;
    var ui = new firebaseui.auth.AuthUI(firebase.auth());
    ui.start("#firebaseui-auth-container", {
      callbacks: {
        uiShown: function() {
          console.log("uiShown");
        },
        signInSuccessWithAuthResult: function(authResult, redirectUrl) {
          console.log("signInSuccessWithAuthResult", authResult, redirectUrl);

          var isNewUser = authResult.additionalUserInfo.isNewUser;
          var displayName = authResult.user.displayName;
          var photoURL = authResult.user.photoURL;

          // SNSログイン&で登録済みであればスキップ
          if (displayName != "ゲスト" && !isNewUser) {
            return true;
          }

          switch (authResult.additionalUserInfo.providerId) {
            case firebase.auth.GoogleAuthProvider.PROVIDER_ID:
              displayName = authResult.additionalUserInfo.profile.name;
              photoURL = authResult.additionalUserInfo.profile.picture;
              break;
            case firebase.auth.FacebookAuthProvider.PROVIDER_ID:
              displayName = authResult.additionalUserInfo.profile.name;
              photoURL = authResult.additionalUserInfo.profile.picture.data.url;
              break;
            case firebase.auth.TwitterAuthProvider.PROVIDER_ID:
              displayName = authResult.additionalUserInfo.profile.name;
              photoURL =
                authResult.additionalUserInfo.profile.profile_image_url;
              break;
            case firebase.auth.GithubAuthProvider.PROVIDER_ID:
              displayName = authResult.additionalUserInfo.profile.name;
              photoURL = authResult.additionalUserInfo.profile.avatar_url;
              break;
            default:
              displayName = "ゲスト";
              photoURL = "";
              break;
          }

          var user = {
            displayName: displayName,
            photoURL: photoURL
          };

          firebase
            .auth()
            .currentUser.updateProfile(user)
            .then(res => {
              console.log("Auth登録完了", res);
              alert("ログインしました。");
              vm.$router.go();
            });
        },
        signInFailure: function(error) {
          console.log("signInFailure", error);
          alert(error.message);
          vm.$router.go();
        }
      },
      autoUpgradeAnonymousUsers: true,
      signInFlow: "redirect",
      signInSuccessUrl: "/",
      signInOptions: [
        firebase.auth.GoogleAuthProvider.PROVIDER_ID,
        firebase.auth.FacebookAuthProvider.PROVIDER_ID,
        firebase.auth.TwitterAuthProvider.PROVIDER_ID,
        firebase.auth.GithubAuthProvider.PROVIDER_ID,
        firebaseui.auth.AnonymousAuthProvider.PROVIDER_ID
      ]
    });
  }
};
</script>
src/components/Logout.vue
<template>
  <div>
    <button @click="accountDelete()">アカウント削除</button>
    <button @click="logout()">ログアウト</button>
  </div>
</template>

<script>
var firebase = require("firebase");

export default {
  name: "Logout",
  props: ["isLogin", "loginUser"],
  methods: {
    // ログアウト
    logout() {
      var vm = this;
      if (!firebase.auth().currentUser) {
        alert("ログインしてください。");
        return;
      }
      firebase
        .auth()
        .signOut()
        .then(function(res) {
          console.log("signOut", res);
          alert("ログアウトしました。");
          vm.$router.go();
        })
        .catch(function(error) {
          console.log(error);
        });
    },
    accountDelete() {
      var vm = this;
      // アカウント削除
      if (!firebase.auth().currentUser) {
        alert("ログインしてください。");
        return;
      }
      firebase
        .auth()
        .currentUser.delete()
        .then(function(res) {
          console.log("currentUser.delete", res);
          alert("アカウントを削除しました。");
          vm.$router.go();
        })
        .catch(function(error) {
          console.log(error);
        });
    }
  }
};
</script>

Gitのブランチに上げました
https://github.com/okdyy75/dev_firebase/tree/firebaseui_vue

okdyy75
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away