Firebase + Vueでログイン機能をつくる

こんにちは。フリーランス・コンサルタント&エンジニアの 九保すこひ です。

さてさて、私は新しい情報を取得できるようにニュースやブログだけでなく、海外の掲示板もチェックするよう心掛けています。

そして、そんな中でたびたび登場するあるキーワードがあって、「時間ができたら試してみよう!」と考えていました。

それは、

サーバーレス 💻

です。

サーバーレスとは、簡単に言うと「サーバー管理はクラウドにおまかせ!」という意味で、サーバー管理の手間を省けるというのが大きなメリットです。

そして!

そんなサーバーレスを実装するサイトはいくつかありますが、私が気になっていたのはよく話題になるGoogleの「Firebase」です。

そこで、今回はFirebaseを使ってログイン関連の機能をつくってみます。

ぜひ皆さんのお役に立てると嬉しいです😊✨

開発環境: Firebase JavaScript SDK 7.12.0

Firebaseの準備

プロジェクトをつくる

まずFirebaseにログインして「プロジェクトを作成」ボタンをクリックしてください。(すみません、登録はその昔にやってしまったので省略させてください😅)

プロジェクトの名前を入力し、規約の同意にチェックを入れたら「続行」ボタンをクリックします。

次にアナリティクスを使うかどうか聞かれますが、今回はテストなのでチェックを外して「プロジェクトを作成」ボタンをクリック。

すると、新しいプロジェクトが作成されます。

プロジェクトの設定

続いてJavaScriptFirebaseを使えるようにします。
</>ボタンをクリックしてください。

そして、アプリの名前を入力して「アプリを登録」ボタンをクリックします。

すると、JavaScriptコードが表示されますが、この中のfirebaseConfigの内容は後で必要になってきますので、控えておいてください。

そして、「コンソールに進む」ボタンをクリックします。

続いてプロダクトを「Authentication」をクリック。

そして、「ログイン方法を設定」をクリック。

Firebaseには認証方法がたくさんありますが、今回は基本的な「メールアドレス + パスワード」を選択します。

すると、以下のようなポップアップが表示されるので「有効にする」にチェックを入れて「保存」ボタンをクリックしてください。

これでFirebaseの準備は完了です!

ログイン、ログアウト、ユーザー登録機能をつくる

では、実際にコードを書いていきましょう。
まずは、基本になる以下3つの機能です。

  • ログイン
  • ログアウト
  • ユーザー登録

auth.html

<html>
<head>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>
<body>
    <div id="app" class="container pt-3">
        <div v-if="sending">
            送信中...
        </div>
        <div v-if="user">
            <h1>ログインが成功しました</h1>
            <button type="button" class="btn btn-primary mb-3" @click="logout">ログアウト</button>
            <pre class="bg-light p-3" v-text="user"></pre>
        </div>
        <div class="row">
            <div class="col-6">
                <div class="form-group">
                    <label>メールアドレス</label>
                    <input type="text" class="form-control" v-model="email">
                </div>
                <div class="form-group">
                    <label>パスワード</label>
                    <input type="password" class="form-control" v-model="password">
                </div>
                <div class="form-group">
                    <button type="button" class="btn btn-danger mr-3" :disabled="sending" @click="register">ユーザー登録</button>
                    <button type="button" class="btn btn-primary" :disabled="sending" @click="login">ログイン</button>
                </div>
            </div>
        </div>
    </div>
    <script src="https://www.gstatic.com/firebasejs/7.12.0/firebase-app.js"></script>
    <script src="https://www.gstatic.com/firebasejs/7.12.0/firebase-auth.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
    <script>

        new Vue({
            el: '#app',
            data: {
                email: '',
                password: '',
                user: null,
                sending: false
            },
            methods: {
                register() {

                    this.sending = true;

                    firebase.auth()
                        .createUserWithEmailAndPassword(this.email, this.password)
                        .catch(error => {   // エラーの場合

                            alert('登録情報が正しくありません。');

                        })
                        .finally(() => {

                            this.sending = false;

                        });

                },
                login() {

                    this.sending = true;

                    firebase.auth()
                        .signInWithEmailAndPassword(this.email, this.password)
                        .catch(error => {   // エラーの場合

                            alert('ログイン情報が間違っています。');

                        })
                        .finally(() => {

                            this.sending = false;

                        });

                },
                logout() {

                    firebase.auth().signOut();

                }
            },
            mounted() {

                // firebaseを準備
                const firebaseConfig = {
                    apiKey: "**********************************",
                    authDomain: "**********************************",
                    databaseURL: "**********************************",
                    projectId: "**********************************",
                    storageBucket: "**********************************",
                    messagingSenderId: "**********************************",
                    appId: "**********************************"
                };
                firebase.initializeApp(firebaseConfig);

                // ログイン状態が変化したら実行
                firebase.auth().onAuthStateChanged(user => {

                    if(user) {

                        this.user = user;
                        this.email = '';
                        this.password = '';

                    } else {

                        this.user = null;

                    }

                });

            }
        });

    </script>
</body>
</html>

この中で重要なのがmounted()内にあるfirebaseConfigの部分です。
ここは、先ほどFirebaseの準備で取得したものを使ってください。

そして、その下にあるonAuthStateChanged()はログイン状態が変化すると実行される部分で、例えばログインやユーザー登録に成功したり、ログアウトした場合に呼ばれることになります。

また、実際にユーザー登録しているのはcreateUserWithEmailAndPassword()で、ログインはsignInWithEmailAndPassword()になり、ユーザー情報がVueで表示されることになります。(ちなみに、ユーザー登録した時点でログインも完了しています)

ユーザー情報を更新する

先ほどのユーザー登録ではメールアドレスとパスワードだけを登録しましたが、Firebaseでは、その他のデータも保存できます。

そこで、今回は「ユーザー名」を登録してみます。

※なお、もちろんHTMLファイルで実行可能ですが、先にログインをしてから実行してください。

update.html

<html>
<head>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>
<body>
    <div id="app" class="container pt-3">
        <div v-if="sending">
            送信中...
        </div>
        <div class="row" v-if="user">
            <div class="col-6">
                <h1>名前を追加してください</h1>
                <div class="form-group">
                    <input type="text" class="form-control" v-model="userName">
                </div>
                <button type="button" class="btn btn-primary" @click="save">保存する</button>
            </div>
            <div class="col-6">
                <h1>ユーザー情報</h1>
                <pre class="bg-light p-3" v-text="user"></pre>
            </div>
        </div>
    </div>
    <script src="https://www.gstatic.com/firebasejs/7.12.0/firebase-app.js"></script>
    <script src="https://www.gstatic.com/firebasejs/7.12.0/firebase-auth.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
    <script>

        new Vue({
            el: '#app',
            data: {
                userName: '',
                user: null,
                sending: false
            },
            methods: {
                save() {

                    this.sending = true;

                    if(this.user){

                        this.user.updateProfile({
                            displayName: this.userName
                        })
                        .catch(error => {

                            alert('失敗しました。');

                        })
                        .finally(() => {

                            this.sending = false;

                        });

                    }

                }
            },
            mounted() {

                // firebaseを準備
                const firebaseConfig = {
                    apiKey: "**********************************",
                    authDomain: "**********************************",
                    databaseURL: "**********************************",
                    projectId: "**********************************",
                    storageBucket: "**********************************",
                    messagingSenderId: "**********************************",
                    appId: "**********************************"
                };
                firebase.initializeApp(firebaseConfig);

                // ログイン状態が変化したら実行
                firebase.auth().onAuthStateChanged(user => {

                    if(user) {

                        this.user = user;

                    } else {

                        this.user = null;

                    }

                });

            }
        });

    </script>
</body>
</html>

この中で実際にFirebaseへデータ送信しているのが、updateProfile()です。そして、displayNameがユーザー名のフィールドになります。

パスワード再発行

では、最後にパスワードを再発行する機能をつくっていきましょう。

<html>
<head>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>
<body>
    <div id="app" class="container pt-3">
        <div class="row">
            <div class="col-6">
                <h1>パスワード再発行</h1>
                <div class="form-group">
                    <label>メールアドレス</label>
                    <input type="text" class="form-control" v-model="email">
                </div>
                <button type="button" class="btn btn-primary" @click="send">送信する</button>
            </div>
        </div>
    </div>
    <script src="https://www.gstatic.com/firebasejs/7.12.0/firebase-app.js"></script>
    <script src="https://www.gstatic.com/firebasejs/7.12.0/firebase-auth.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.min.js"></script>
    <script>

        new Vue({
            el: '#app',
            data: {
                email: ''
            },
            methods: {
                send() {

                    firebase.auth().languageCode = 'ja'; // 日本語に設定
                    firebase.auth()
                        .sendPasswordResetEmail(this.email)
                        .then(() => {

                            alert('パスワード再発行URLを送信しました。');

                        }).catch(error => {

                            alert('該当するデータが見つかりませんでした。');

                        });

                }
            },
            mounted() {

                // firebaseを準備
                const firebaseConfig = {
                    apiKey: "**********************************",
                    authDomain: "**********************************",
                    databaseURL: "**********************************",
                    projectId: "**********************************",
                    storageBucket: "**********************************",
                    messagingSenderId: "**********************************",
                    appId: "**********************************"
                };
                firebase.initializeApp(firebaseConfig);

            }
        });

    </script>
</body>
</html>

コード的にはボタンが押されたらsendPasswordResetEmail()が実行されるシンプルなものです。

このメソッドが実行されるとFirebaseの方から次のような再発行メールが届きますので、パスワードを変更する場合はURLをクリックします。

すると以下のようなフォームが表示されるのでパスワードを送信。

Firebaseがパスワードを変更してくれます。

開発のご依頼お待ちしております
開発のご依頼はこちらから: お問い合わせ
どうぞよろしくお願いいたします! by 九保すこひ

おわりに

ということで今回はサーバーレスなログイン機能を作ってみました。

個人的にサーバーレスは初めての経験でしたが、HTMLファイルさえあれば実行できるのは大きなメリットです!

(・・・ということは、Electronでも使いやすいですね)

逆にデメリットに感じたのは、何をするにもFirebaseの決めたルールを使わないといけませんが、この会社を所有しているGoogleは頻繁に内容を変更しますし、ひどいときはサービスを急に終了するので、長期展望としては少し不安ではありますよね😅

とはいえ、技術的にはとても魅力的なので興味を持たれた方はぜひチャレンジしてみてくださいね。(なんなら専用のサーバーレス・サイトを作っておいても面白いかもしれません)

ではでは〜!

このエントリーをはてなブックマークに追加       follow us in feedly