Firebase Authentication - その2
「Firebase のユーザー認証システムで、Web クライアント認証を実装してみます」 の続きです.
今回は、ユーザ登録とログイン画面を追加して、ログイン・ログアウトを実装してみます.
ユーザ登録とログインは別の画面になるので、 Vue router を使って SPA (Single Page App) にします。
Vue router をプロジェクトに追加します。
$ npm install vue-router --save
src/component/(Home|SignUp|SingIn).vue
に空のページを用意しておきます。
<template>
<div class="home">
<h1>This is Home page</h1>
</div>
</template>
src/router/index.js
にルートを設定します。
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '@/components/Home'
import SignUp from '@/components/SignUp'
import SignIn from '@/components/SignIn'
Vue.use(VueRouter)
const routes = [
{
path: '/',
name: 'Home',
component: Home,
},
{
path: '/signup',
name: 'SignUp',
component: SignUp
},
{
path: '/signin',
name: 'SignIn',
component: SignIn
},
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
});
export default router
src/main.js
に router を使うように設定します。
import router from './router'
new Vue({
router,
render: h => h(App),
}).$mount('#app')
App.vue
は、 router の現ページを表示するように設定しておきます。
<template>
<div id="app">
<router-view/>
</div>
</template>
<router-view/>
が router の設定によって内容が切り替わる SPA のできあがりです。
http://localhost:8080/signin/
などにアクセスして、それぞれのページが表示されているか確認します。
ここまでの変更は、以下のブランチで確認できます。
では、実際にアカウントを登録する画面を作成します。 SignUp.vue
を変更します。
<template>
<div class="signup">
<form @submit.prevent="onSignUp">
<div class="input-row">
<label>メールアドレス:</label>
<input id="email" type="email" v-model="mailaddress" />
</div>
<div class="input-row">
<label>パスワード:</label>
<input id="password" type="password" v-model="password" />
</div>
<button type="button" class="btn" @click.prevent.self="onClear">クリア</button>
<button type="submit" class="btn">登録</button>
</form>
<div class="message">{{ message }}</div>
</div>
</template>
<script>
import firebase from 'firebase/app';
import 'firebase/auth';
import { firebaseErrors } from '../fbMessage';
export default {
name: "SignUp",
data() {
return {
mailaddress: '',
password: '',
message: '',
};
},
methods: {
onClear: function() {
console.log('onClear');
this.mailaddress = '';
this.password = '';
this.message = '';
},
onSignUp: function () {
this.message = '';
let auth = firebase.auth();
auth.useDeviceLanguage();
auth.createUserWithEmailAndPassword(this.mailaddress, this.password)
.then(() => {
// 成功時の処理
console.log("signup success");
if (!alert('メールアドレス「' + this.mailaddress + '」を登録しました.')) {
this.$router.push('/');
}
})
.catch((err) => {
// エラー時の処理
console.log(err);
this.message = firebaseErrors[err.code] || err.message;
});
},
},
};
</script>
ユーザ名とパスワードの入力項目があるだけの単純な画面です。

入力されたアカウント情報を firebase.auth().createUserWithEmailAndPassword()
に渡します。
あとは、firebase 側で処理されて、認証が成功したら then()
になります。
catch()
の処理ですが、firebase のエラーコードをみて、適当な日本語メッセージを出します。
メッセージは、 fbMessage.js
に定義しています。 (本来は他言語対応とかしておくと良いですが、今回は省略)
出力されるエラーコードは、Admin Authentication API エラー に一覧があるので、適宜翻訳を追加していきます。 該当するエラーコードがない場合には、オリジナルの英語のメッセージが表示されます。
ユーザ登録が行われると、 Firebase コンソールの Authentication
セクションにユーザ情報が追加されていきます。

Firebase コンソールを見るとわかりますが、ユーザーのパスワード情報などは Firebase 側で管理されるので、たとえ管理者でも参照できません。
Google のクラウド全体がクラックされたりしなければ大丈夫なレベルの、セキュリティが担保されると考えても良いのではないでしょうか。
登録と同様に、 SignIn.vue
を変更してログイン用の画面を作ります。
<template>
<div class="signin">
<form>
<div class="input-row">
<label>メールアドレス:</label>
<input id="email" type="email" v-model="mailaddress" />
</div>
<div class="input-row">
<label>パスワード:</label>
<input id="password" type="password" v-model="password" />
</div>
</form>
<button class="btn" @click="onClear">クリア</button>
<button class="btn" @click="onSignIn">ログイン</button>
<div class="message">{{ message }}</div>
</div>
</template>
<script>
import firebase from "firebase/app";
import 'firebase/auth';
import { firebaseErrors } from '../fbMessage';
export default {
name: "SignIn",
data() {
return {
mailaddress: '',
password: '',
message: '',
};
},
methods: {
onClear: function() {
this.mailaddress = '';
this.password = '';
},
onSignIn: function () {
this.message = '';
let auth = firebase.auth();
auth.useDeviceLanguage();
auth.signInWithEmailAndPassword(this.mailaddress, this.password)
.then(() => {
// 成功時の処理
console.log("signin success");
if (!alert('ログインしました')) {
this.$router.push('/');
}
})
.catch((err) => {
// エラー時の処理
console.log(err);
this.message = firebaseErrors[err.code] || err.message;
});
},
},
};
</script>
構造は、SignUpとほぼ同じです。入力されたアカウント情報を firebase.auth().signInWithEmailAndPassword()
に渡します。
あとは、firebase 側で処理されて、ログインできたら then()
の $router.push('/')
になり、成功したら、Home.vue
に戻ります。
Home.vue
を変更して、ユーザのログイン状態を検知して変化するようにしてみます。
そのために、 onAuthStateChanged
にオブザーバを登録します。
ログイン状態が変化するたびに、オブザーバが呼ばれます。
パラメータの user
は、 Userのプロパティ に詳しい説明があります。
mounted: function () {
firebase.auth().onAuthStateChanged((user) => {
if (user) {
// ログインしていれば中通る
this.user = user;
console.log("user", user); // ユーザー情報が表示される
user.getIdToken(true).then((token) => (this.token = token));
} else {
this.token = null;
}
});
},
また、 user.getIdToken()
は、サーバ側で認証されたユーザーからのアクセスかチェックするためのトークンを取得します。
そちらについては、後ほど詳しく見ていきます。
App.vue
でも同じように、 onAuthStateChanged
にオブザーバを登録して、ログインしているならログアウトのリンクを表示するようにして、ログアウト処理をしてみます。
methods: {
onLogout: function() {
firebase.auth().signOut()
.then(() => {
// 成功時の処理
console.log("logout success");
if (!alert('ログアウトしました')) {
this.$router.go();
// this.$router.push('/');
}
})
.catch((err) => {
// エラー時の処理
console.log(err);
this.message = firebaseErrors[err.code] || err.message;
});
}
}
firebase.auth().signOut()
を呼び出すだけです。
この時点での変更は、以下のブランチで確認できます。
vue-firebase-auth - signin ブランチ
firebase.auth()
の signInWithEmailAndPassword()
でログインして、signOut()
でログアウトします。
onAuthStateChanged
にオブザーバーを登録してログイン状態を把握するというのが基本的な流れです。
ユーザからの入力受け付けや後処理などを除けば、それぞれ1行だけで完了なので、とても簡単に堅牢な認証システムを導入できます。
このあとは、サーバ側で認証状態の確認をしてみます。