JavaScript
Vue.js
Firebase

Firebase+Vue.jsで大学の関係者だけが見れるサイトをサクッと作る

4/14 追記 : この方法はフロントでメアドの判別をしているため、やろうと思えば中身を見ることが出来てしまいます。本当に見られたくないページを作成したい場合、Cloud Functionsを使うことでバックエンドでデータを取れなくなり見れなくなるという設計になります。 @potato4d さん @302u2weさん 鋭いご指摘ありがとうございます。 正しい実装は @potato4dさんのコメントにあります。よろしくお願い致します。


注意

大学がG Suiteを使っている前提です。

大学のメールアドレスでGoogleにログイン出来たらG suiteです。


この記事でやること

バックエンドをFirebaseに丸投げしてGoogleアカウント認証でのログイン → ユーザ情報(ユーザのメアド)による表示の切り替え → サインアウト までの簡単なチュートリアルです。


大学の関係者の認証方法

大学の関係だけが見ているという状態にする方法は中々考え付かないです。また認証回りが非常に面倒で、仮に作ったとしてもセキュリティに不安が残ります。

そこでBaaS(Backend as a Service)であるFirebaseを使って簡単にユーザ認証を実装しましょう


環境

今回はWindowsで進めていきます。

IDEはWebStorm2019.1で。

C:\Users\leima>node -v

v10.15.3

C:\Users\leima>vue -V
3.5.5

WebStormのFile -> New -> Project からVue.jsを選びましょう。

image.png

Project nameはお好みで。

今回はこんな感じで進めていきます

image.png

Descriptionもご自由に

image.png

Authorも自由に設定して、

image.png

残りの設定は以下のような感じで

image.png

image.png

image.png

image.png

(入力切り替えくん迫真の妨害)

image.png

image.png

image.png

大体こんな感じになったら、右上の開始ボタンを押してとりあえず動かしてみましょう。

image.png

image.png

上記のように表示されればOKです。


認証画面を作る

App.vueを直接弄ってサクッと作りましょう。


src/App.vue

<template>

<div id="app">
<img src="./assets/logo.png"
alt="vue">
<h2>Welcome!</h2>
<button>Auth</button>
</div>
</template>

<script>

export default {
name: 'App',
components: {
}
}
</script>

<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>


以上のように変更したら以下のような画面になると思います。

image.png


バックエンド部の実装

画面が出来たらバックエンドをFirebaseで設定しましょう。

image.png

こんな感じになればOK

image.png

Firebaseの設定をプロジェクトに反映させましょう。 画像の部分をクリックしてください。

image.png

クリック後、プロジェクト設定のためのJavaScriptのコードが表示されます。このコードをjsに組み込みましょう。


src/main.js

import Vue from 'vue'

import App from './App'
import firebase from 'firebase'

Vue.config.productionTip = false
const config = {
apiKey: 'YOUR_KEY',
authDomain: 'YOUR_DOMAIN.firebaseapp.com',
databaseURL: 'YOUR_DOMAIN.firebaseio.com',
projectId: 'YOUR_ID',
storageBucket: 'YOUR_BUCKET_ID.appspot.com',
messagingSenderId: 'YOUR_SENDER_ID'
}
firebase.initializeApp(config)
/* eslint-disable no-new */
new Vue({
el: '#app',
components: { App },
template: '<App/>'
})


Firebaseの設定に戻り、サイドバーの 開発-> Authentication に移動します。

image.png

ログイン方法を選択し、Googleのステータスの編集をしましょう。

image.png

image.png

保存を押したら有効になってることを確認しましょう。

image.png


ユーザ認証のコードの追加

App.vueを以下のようにして、ボタンが押されたら認証を開始するようにします。


src/main.js

<template>

<div id="app">
<img src="./assets/logo.png"
alt="vue">
<h2>Welcome!</h2>
<button @click="logIn">Auth</button>
</div>
</template>

<script>

import * as firebase from 'firebase'

export default {
name: 'App',
components: {
},
methods: {
logIn: function () {
const provider = new firebase.auth.GoogleAuthProvider()
firebase.auth().signInWithRedirect(provider).then()
}
}
}
</script>

<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>


よく見ると、

const provider = new firebase.auth.GoogleAuthProvider()

firebase.auth().signInWithRedirect(provider).then()

だけでGoogle認証が出来ています。 プロバイダを作って、リダイレクトで認証させてるってことですね。

一度動作を確認してみましょう。

ボタンをクリック -> Googlerアカウント選択 -> 最初の画面に戻る

この動作になっていればOKです。

image.png

image.png

image.png


ユーザの認証状態を取得する。 

firebase.auth().onAuthStateChanged()をつかって簡単にリッスン出来ます。しかもログイン中のユーザの情報も取れるので非常に便利、mounted()においてしまいましょう


src/App.vue

<template>

<div id="app">
<img src="./assets/logo.png"
alt="vue">
<h2>Welcome!</h2>
<button @click="logIn">Auth</button>
{{this.currentUser}}
</div>
</template>

<script>

import * as firebase from 'firebase'

export default {
name: 'App',
props: {
currentUser: {
type: firebase.User,
default: null
},
unsubscribe: {
type: Function
}
},
components: {
},
methods: {
logIn: function () {
const provider = new firebase.auth.GoogleAuthProvider()
firebase.auth().signInWithRedirect(provider).then()
}
},
mounted () {
this.unsubscribe = firebase.auth().onAuthStateChanged(user => {
if (user) {
this.currentUser = user
} else {
this.currentUser = null
}
})
}
}
</script>

<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>


実行後、いろんな情報がボタンの右に書いてあったらOKです。

後は、ログアウトボタンを作ったり、ログインしてるかによって内容を変えてみましょう。

以下の様にApp.vueを修正してみます。


src/App.vue

<template>

<div id="app">
<img src="./assets/logo.png"
alt="vue">
<h2>Welcome!</h2>
<div v-if="this.currentUser">
<h2>Hello, {{this.currentUser.displayName}} さん</h2>
<button @click="logOut">LogOut</button>
</div>
<div v-else>
<button @click="logIn">Auth</button>
</div>
</div>
</template>

<script>

import * as firebase from 'firebase'

export default {
name: 'App',
props: {
currentUser: {
type: firebase.User,
default: null
},
unsubscribe: {
type: Function
}
},
components: {
},
methods: {
logIn: function () {
const provider = new firebase.auth.GoogleAuthProvider()
firebase.auth().signInWithRedirect(provider).then()
},
logOut: function () {
firebase.auth().signOut().then().catch(
(err) => alert(err)
)
}
},
mounted () {
this.unsubscribe = firebase.auth().onAuthStateChanged(user => {
if (user) {
this.currentUser = user
} else {
this.currentUser = null
}
})
}
}
</script>

<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>


こんな感じになれば成功です。(Helloの後がGoogleアカウントの表示名になると思います。)

image.png


大学の関係者のみ閲覧可能にする。

大学から配布されているメールアドレスを確認しましょう。

私はexample大学に所属しているので、

~@stu.example.ac.jp

というメールアドレスを頂いています。また、教授陣は~@example.ac.jpというメールアドレスを持っています。

this.currentUser.emailでGoogleアカウントのメールアドレスを確認して、その文字列が含まれているかどうかで場合分けをしましょう。


src/App.vue

<template>

<div id="app">
<img src="./assets/logo.png"
alt="vue">
<div v-if="this.currentUser">
<div v-if="~this.currentUser.email.indexOf('@stu.example.ac.jp')">
<h1>
<h2>Welcome!</h2>
Welcome {{this.currentUser.displayName}} さん! (学生)
</h1>
</div>
<div v-else-if="~this.currentUser.email.indexOf('@example.ac.jp')">
<h1>
<h2>Welcome!</h2>
Welcome {{this.currentUser.displayName}} さん!
</h1>
</div>
<div v-else>
申し訳ございません。このサイトの閲覧は大学のメールアドレスを持つ方のみ許可されています。
</div>
<button @click="logOut">LogOut</button>
</div>
<div v-else>
<h2>Welcome!</h2>
<button @click="logIn">Auth</button>
</div>
</div>
</template>

<script>

import * as firebase from 'firebase'

export default {
name: 'App',
props: {
currentUser: {
type: firebase.User,
default: null
},
unsubscribe: {
type: Function
}
},
components: {
},
methods: {
logIn: function () {
const provider = new firebase.auth.GoogleAuthProvider()
firebase.auth().signInWithRedirect(provider).then()
},
logOut: function () {
firebase.auth().signOut().then().catch(
(err) => alert(err)
)
}
},
mounted () {
this.unsubscribe = firebase.auth().onAuthStateChanged(user => {
if (user) {
this.currentUser = user
} else {
this.currentUser = null
}
})
}
}
</script>

<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>


この状態で適当なメアドで認証してみると、こうなると思います。

image.png

これで大学の関係者のみがみれるサイトを作る事が出来ました。

応用する事で社員のみアクセス出来るサイトなどを簡単に作る事ができると思います。


まとめ

いかかでしたでしょうか。FirebaseのGoogle認証を使って、メールアドレスでユーザを判別するという手法でしたが非常に簡単に作る事が出来たと思います。

私自身VueというかJavaScriptを初めて1ヶ月も経たないくらいの超初心者ですがそれでも簡単に実装が出来ていてFirebaseの凄さを感じました。

学内向けのサービスなどを考えるときにも非常に有用な手法になると思います。


おまけ

上記の方法で一度ログインをすると、次回のログインはアカウントの選択が入らない場合があります。

すなわち、一度アカウントの選択を間違えると、キャッシュを消したりしない限り、選び直せないという・・・

これの解決をしようとそこそこはまっていたのですが良い記事がstack overflowにあったためそれについて共有したいと思います。

Firebase google auth automatically selecting user. How to force it to select account

結論は簡単で

providerの定義後に以下の様にパラメータを設定する事でアカウントの選択を強制させる事が出来ます。

const provider = new firebase.auth.GoogleAuthProvider();

provider.setCustomParameters({ prompt: 'select_account consent'});


参考

Vue.js + Firebase を使って爆速でユーザ認証を実装する https://qiita.com/sin_tanaka/items/ea149a33bd9e4b388241