Edited at

FirebaseUI + vueでログイン処理


概要

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