vue.jsのログイン認証をFirebase Authenticationを使って構築

FirebaseのAuthenticationを利用してvue.jsでのログイン認証の動作確認を行います。本文書ではindex.htmlとcdnを使って動作確認を行うので、実用的なログイン認証の実装ではありませんが本文書を読めばFirebase Authenticationの基本を理解することができます。
目次
Firebaseの設定
アカウント登録
Firebaseのユーザアカウントを持っていない人はまずユーザ登録を行う必要があります。Firebaseのユーザアカウントを持っている人は次の”プロジェクトの作成”に進んでください。

ページが開いたら真ん中にある使ってみるボタンをクリックします。

ログイン画面が表示されるので、メールアドレスを入力します。次へボタンにいくとパスワードを聞かれるので入力してください。

Firebaseへようこそ画面が表示されればアカウント登録は完了です。

プロジェクトの作成
Firebaseにログインするとプロジェクトの作成画面が表示されます。”プロジェクトを追加”をクリックしてください。


プロジェクト名を入力する画面が表示されるので任意の名前をつけてください。ここではvue.jsのログイン認証の動作確認を行うので、vue-authenticationという名前にしています。

Googleアナリティクスを利用するかどうか確認画面が表示されます。デフォルトでは有効にするになっていますが今回Google Analyticsの利用はないので無効にしてプロジェクト作成ボタンをクリックします。

プロジェクトの作成画面が表示されます。新しいプロジェクトの準備ができましたと表示されたら、続行ボタンをクリックしてください。

プロジェクトのコンソール画面が表示されます。

Authentication(認証)の設定
コンソール画面のAuthenticationユーザの認証と管理をクリックしてください。

Authenticationの設定画面が表示されます。画面真ん中の”ログイン方法を設定”ボタンをクリックしてください。

Googleのアカウントだけではなく様々なプロバイダを利用してログイン設定を行うことができます。ここでは一番上のプロバイダのメール/パスワードをクリックしてください。

メールとパスワードを使った認証を有効にするため、有効にするに変更してください。デフォルトでは有効にするが選択されていません。有効にするに変更後、保存ボタンをクリックしてください。

メール/パスワードのステータスが有効になっていることが確認できます。

ウェブアプリの登録
Authenticationをウェブアプリから利用するためには、SDKが必要となります。SDKはアプリを登録することで取得することができます。
下記の赤四角で囲まれた</>をクリックします。

アプリの名前を入力する画面が表示されるので、任意の名前をつけます。入力後、アプリを登録ボタンをクリックしてください。

ウェブアプリで利用するためのSDKの情報が表示されるので、これらの情報をコピーしてファイルに貼り付けます。


ここではindex.htmlを使って動作確認を行うので下記のように貼り付けを行います。
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<!-- The core Firebase JS SDK is always required and must be listed first -->
<script src="https://www.gstatic.com/firebasejs/7.2.0/firebase-app.js"></script>
<script src="https://www.gstatic.com/firebasejs/7.2.0/firebase-auth.js"></script>
</head>
<body>
<h1>ユーザ登録画面</h1>
<script>
// Your web app's Firebase configuration
var firebaseConfig = {
apiKey: "AIzaSyC76lXHmeAAeimabsC0DKm8ZwG9tBS26ds",
authDomain: "vue-authentification-e4051.firebaseapp.com",
databaseURL: "https://vue-authentification-e4051.firebaseio.com",
projectId: "vue-authentification-e4051",
storageBucket: "vue-authentification-e4051.appspot.com",
messagingSenderId: "396852998505",
appId: "1:396854998605:web:2f69512997341e7a390df8"
};
// Initialize Firebase
firebase.initializeApp(firebaseConfig);
</script>
</body>
</html>

ここまででFirebase側での設定は完了でこれからvue.jsの設定を行い認証の動作確認を行なっていきます。
vue.jsの設定
認証用フォームの作成
手元のパソコンでも簡単に動作確認できるようにvue.jsはcdnを使って読み込みます。フォームを作成するためにbootstrapも利用しているためbootstrapもcdnを使います。
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" >
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
入力フォーム部分は下記のように記述します。メールアドレスとemailの入力欄があるシンプルなフォームです。
<div id="app" class="container mt-5">
<h2>ユーザ登録画面</h2>
<div class="row">
<div class="col-sm-8">
<form @submit.prevent="registerUser">
<div class="form-group">
<label for="email">メールアドレス:</label>
<input type="email" class="form-control" id="email" v-model="email">
</div>
<div class="form-group">
<label for="password">パスワード:</label>
<input type="password" class="form-control" id="password" v-model="password">
</div>
<button type="submit" class="btn btn-info">登録</button>
</form>
</div>
</div>
</div>
vue.jsではデータプロパティにemail, passwordを追加し、input要素にはv-modelでemailとpasswordを追加します。
登録ボタンを押すとsubmitFormメソッドが実行されるようにhtml側のformタグにsubmitイベントを追加します。submitイベントではregisterUserメソッドを設定しています。

const app = new Vue({
el: '#app',
data: {
email: '',
password: ''
},
methods: {
registerUser(){
}
}
});
ブラウザで確認すると入力フォームが下記のように表示されます。

Firebase Authenticationを利用する
Firebase SDK、vue.jsによるログインフォームが完了したので、これからFirebase Authenticationの設定を行います。
公式ドキュメントの”ウェブサイトでFirebase Authenticationを使ってみる”を参考に設定を行なっていきます。ドキュメントには認証に利用できるメソッドの情報が記述されています。
ユーザを登録する
公式ドキュメントの記載通りユーザの作成はcreateUserWithEmailAndPasswordメソッドを使って行います。
コードのregisterUserメソッドにcreateUserWithEmailAndPasswordメソッドを追加して、引数に入力フォームで入力されたemailとpasswordを渡します。
methods: {
registerUser(){
console.log(firebase);
firebase.auth().createUserWithEmailAndPassword(this.email, this.password).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
});
}
}
入力フォームにemailアドレスとパスワードを入力して登録するボタンをクリックします。


登録が正常に行われるとFirebaseのAuthenticationのコンソールにユーザが登録されます。

同じメールアドレスを登録しようとするとコンソールには下記のエラーが表示されます。
auth/email-already-in-use
The email address is already in use by another account.
ユーザのログイン状態の変化を確認
ここまでの設定でユーザの登録を行うことができましたが、現在ユーザがログイン状態なのかログアウト状態を知ることができません。ログイン、ログアウト状態の変化を知るためのメソッドonAuthStateChangedが準備されているのでどうのように使用するのか確認しましょう。
onAuthStateChangedメソッドは、ユーザーのログイン状態が変わるたびに呼び出されるメソッドなのでライフサイクルフックmountedに設定します。
mounted(){
firebase.auth().onAuthStateChanged(function(user) {
if (user) {
console.log('login');
} else {
console.log('logout');
}
});
}
ユーザがログインすればコンソールにloginと表示され、ログアウトすればコンソールにlogoutと表示されるように設定しています。
ログインフォーム、ログアウトボタンを追加
ユーザがログイン、ログアウトを行うため仕組みがないたので作成していきます。新たにログインフォームとログアウトボタンのhtmlを追加します。
<div id="app" class="container mt-5">
<button class="btn btn-primary mb-3" @click="logoutUser">ログアウト</button>
<div class="row">
<div class="col-sm-6">
<h2>ユーザ登録画面</h2>
<form @submit.prevent="registerUser">
<div class="form-group">
<label for="email">メールアドレス:</label>
<input type="email" class="form-control" id="email" v-model="email">
</div>
<div class="form-group">
<label for="password">パスワード:</label>
<input type="password" class="form-control" id="password" v-model="password">
</div>
<button type="submit" class="btn btn-info">登録する</button>
</form>
</div>
<div class="col-sm-6">
<h2>ログイン画面</h2>
<form @submit.prevent="loginUser">
<div class="form-group">
<label for="loginEmail">メールアドレス:</label>
<input type="loginEmail" class="form-control" id="loginEmail" v-model="loginEmail">
</div>
<div class="form-group">
<label for="loginPassword">パスワード:</label>
<input type="password" class="form-control" id="loginPassword" v-model="loginPassword">
</div>
<button type="submit" class="btn btn-info">ログインする</button>
</form>
</div>
</div>
</div>
htmlを変更後にブラウザで確認すると下記のように表示されます。

ログアウトボタンにはクリックイベントでlogoutUserメソッド、ログインフォームにはsubmitイベントでloginUserメソッドを設定しています。
vue.jsには、ログインフォーム用にデータプロパティloginEmail, loginPasswordを追加し、logoutUser, loguinUserメソッドの追加を行います。
ログイン、ログアウトについてはfirebase.authにsignOutメソッドとsignInWithEmailAndPasswordメソッドがあるのでそれを利用します。

methods: {
registerUser(){
firebase.auth().createUserWithEmailAndPassword(this.email, this.password).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
console.log(errorCode);
console.log(errorMessage);
});
},
logoutUser(){
firebase.auth().signOut();
},
loginUser(){
firebase.auth().signInWithEmailAndPassword(this.loginEmail, this.loginPassword).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
console.log(errorCode);
console.log(errorMessage);
});
}
},
ログイン、ログアウトの動作確認
ログイン、ログアウトの設定が完了したので動作確認を行います。それぞれの処理が行われるとonAuthStateChangedが呼び出されて、ログイン/ログアウト状態を確認することができます。
ブラウザでページを開くとonAuthStateChangedが実行されデベロッパーツールのコンソールにlogoutが表示されます。

ページを開いたあとにログアウトボタンを押してください。logout状態であれば状態の変化はないので何も表示されません。ログインしている場合は、ログアウトボタンを押すとlogoutとコンソールに表示されます。
ログイン画面に登録したメールアドレスとパスワードを入力してログインするボタンをクリックします。

ログインするとコンソールにはloginと表示されます。ブラウザをリロードしてみましょう。リロードしてもログイン状態を保っているので、ページを開くとloginと表示されます。
ログアウトボタンを押してください。ログアウトを押すとコンソールにlogoutと表示されます。
firebase.authのメソッドを利用することでログイン、ログアウトが行えることがわかりました。
ページ上で現在のログイン状態を確認し、ログイン状態の場合は、登録フォームとログインフォームを非表示にし、ログアウト状態の場合は、ログアウトボタンを非表示にしたいものです。
現在の状態を利用してページ内容を変更
現在のログイン状態をページ上でも確認できるように新たにデータプロパティAutheticatedUserを追加します。
onAuthStateChangedメソッドを利用して、AutheticatedUserの値を変えます。
const app = new Vue({
el: '#app',
data: {
email: '',
password: '',
loginEmail: '',
loginPassword: '',
authenticatedUser: ''
},
// 中略
mounted(){
firebase.auth().onAuthStateChanged((user) => {
if (user) {
console.log('login');
this.authenticatedUser = true;
} else {
console.log('logout');
this.authenticatedUser = false;
}
});
}
});
v-ifディレクティブを利用して表示の切り替えを行います。
<button class="btn btn-primary mb-3" @click="logoutUser" v-if="authenticatedUser">ログアウト</button>
<div class="row" v-else>
<div class="col-sm-6">
<h2>ユーザ登録画面</h2>
<form @submit.prevent="registerUser">
<div class="form-group">
<label for="email">メールアドレス:</label>
<input type="email" class="form-control" id="email" v-model="email">
</div>
設定が完了したらv-ifディレクティブの動作確認を行います。
logoutの状態でアクセスすると登録画面とログイン画面が表示されます。ログインフォームにメールアドレスとパスワードを入力してログインするボタンを押します。

ログインが完了するとv-ifディレクティブにより、ログアウトボタンのみの表示となります。

ログアウトボタンを押すとログアウトボタンが消えて入力フォームが表示されます。

input要素に入力した内容が表示されているのはログイン完了後にloginEmailとloginPasswordをそのままにしているためです。ログイン完了後に下記の処理を追加すればログイン完了後に入力したメールアドレスとパスワードは消えます。
loginUser(){
firebase.auth().signInWithEmailAndPassword(this.loginEmail, this.loginPassword)
.then(()=>{
this.loginEmail = '';
this.loginPassword = '';
})
.catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
console.log(errorCode);
console.log(errorMessage);
});
}
ルーティングによるページの遷移のないindex.htmlファイルのみで認証の動作確認を行いましたが、firebase.authで使用できるメソッドも確認することができたので、Firebase Authenticationを使う上で基本となる知識は得られたかと思います。