たった50行のhtml, jsで実装！Firebase Authenticationで認証機能を作るハンズオン

# 完成図

未ログイン時
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199678/411b5241-9555-6119-c804-f336d18c6eb6.png" width="300">

ログイン時
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199678/54db3091-df9e-e92c-e410-2112c977b8e7.png" width="300">

# Firebase Authenticatonとは

![firebase_auth.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199678/c105362d-f89b-2085-5579-a09b42f7b096.png)

Googleが提供するmBaaS『Firebase』の機能の一つです。
バックエンド・インフラの管理を気にせず、Firebaseコンソール上のいくつかの設定と、フロントエンドにJavaScriptを少し書くだけで、簡単に認証機能が実装できます。

Firebaseの他の機能を使わずとも、これだけ単体で導入することもできます。

# 自力で認証実装することの大変さ

そもそも認証を自力で実装するのは、機能面とセキュリティ面から、どんな言語であっても大変です。

機能面では、単純に登録・ログイン・ログアウトを作るのも手間ですし、パスワード再発行・メールアドレス変更、退会といった基本機能は想像以上に多いです。
セキュリティ面では、ブルートフォースアタック等の攻撃対策やトークンの管理方法等、考慮することが非常に多く、それらを漏れなく機能実装するのも大変です。

例えばRuby on Railsならdeviseを入れることで簡略化はできますが、結局のところユーザーのパスワードやトークン、ロック日時等を自前のデータベースに実装しなければなりません。

# Firebase Authenticationで楽になることの一例

## フロントエンド
- セッション永続化や、トークンの管理方法(cookie? localStorage?)からの解放
    - ログイン時やログアウト時もfirebaseのメソッドを呼べば簡単にできる

## バックエンド
- Twitter, Facebook, Google等のソーシャルログイン機能の実装がすごく簡単
- アタックに対しての対策や、セキュリティアップデートからの解放

## インフラ
- パスワード等を自前のサーバに管理することからの解放
- 負荷分散等の管理からの解放

# でも、お高いんでしょう…？

そんなことはありません。
Firebaseはプランを無料か有料か選ぶことができ、有料は従量課金となります。
が、個人開発レベルで使うだけなら無料プランで十分ですし、Authenticationで課金要素は電話番号認証を使う時だけです。

# ハンズオン

必要なもの

- Ruby
    - localhostで実行するため、Webサーバが必要になる。Webサーバを立ち上げられるなら他言語でもOK
- Googleアカウント

なお、今回は必要最低限の知識と最小工数を目指すため、フロントエンドも素のHTML5とJavaScriptでいきます。

ステップは全部で4つです。

1. Firebaseプロジェクトの作成
2. Firebase Webアプリケーションの作成
3. Firebase Authenticationの設定
4. フロントエンドの実装

## 1. Firebaseプロジェクトの作成

- https://console.firebase.google.com/
- 「プロジェクトを追加」選択
- プロジェクトの名前は、判別できれば何でもOK
    - なお、プロジェクト名はグローバルでユニークなものになるため、`test`のように既に作られているプロジェクト名を指定すると末尾にランダムな文字列が付く
- GoogleアナリティクスはOFFでOK

これだけでプロジェクトが作られる。

## 2. Firebase Webアプリケーションの作成

ダッシュボードの以下アイコンから、Webアプリの追加を行う
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199678/66adce58-b169-8ee5-fe86-fef037bdf84a.png" width="360">

- アプリ名は、これも認識できれば自由に付けてOK
- Hostingは今回は使わない
- Firebase Admin SDKのソースも一旦無視して続行

## 3. Firebase Authenticationの設定

- 左メニュー「開発」から、Authenticationを選択
- 「始める」ボタン押下
- ログインプロバイダで使える認証方法が一覧表示される
- 「Google」選択
    - 「有効にする」
    - 公開名は「テストアプリケーション」とか自由に設定OK
    - サポートメールは自分のメールアドレスを選択して保存

これだけで、Google認証のバックエンド側設定が完了しました。

## 4. フロントエンドの実装

- ローカルで適当なディレクトリを作成し、index.htmlを作成
- 以下ソースコードを貼り付け。

```html:index.html
<!DOCTYPE html>
<html lang="ja">
    <head>
        <meta charset="utf-8">
        <script src="https://www.gstatic.com/firebasejs/8.0.2/firebase-app.js"></script>
        <script src="https://www.gstatic.com/firebasejs/8.0.2/firebase-auth.js"></script>
        <script>
        // Your web app's Firebase configuration
        var firebaseConfig = {
            apiKey: "XXXXXXXX",
            authDomain: "XXXXXXXX",
            databaseURL: "XXXXXXXX",
            projectId: "XXXXXXXX",
            storageBucket: "XXXXXXXX",
            messagingSenderId: "XXXXXXXX",
            appId: "XXXXXXXX"
        };
        firebase.initializeApp(firebaseConfig);
        </script>
        <script src="https://www.gstatic.com/firebasejs/ui/3.5.2/firebase-ui-auth__ja.js"></script>
        <link type="text/css" rel="stylesheet" href="https://cdn.firebase.com/libs/firebaseui/3.5.2/firebaseui.css" />
    </head>
    <body>
        <div id="firebaseui-auth-container">
        </div>
        <script>
            firebase.auth().onAuthStateChanged(function(user) {
            if (user) { // ログイン時
                console.log(user);  // firebaseから受け取ったユーザー情報。本番運用時はconsole.logは消すこと
                var loginText = "ようこそ" + user.displayName + 'さん ' + user.email + "<button onclick='logOut()'>ログアウト</button>";
                document.getElementById('firebaseui-auth-container').innerHTML = loginText;
            } else {  // 未ログイン時
                var ui = new firebaseui.auth.AuthUI(firebase.auth());
                ui.start('#firebaseui-auth-container', {
                    signInSuccessUrl: '/',
                    signInOptions: [
                        firebase.auth.GoogleAuthProvider.PROVIDER_ID,
                    ],
                });
            }
            });
            function logOut() {
                firebase.auth().signOut().then(function() {
                    location.reload();
                });
            }
        </script>
    </body>
</html>
```

変更が必要な箇所

```js
        var firebaseConfig = {
            apiKey: "XXXXXXXX",
            authDomain: "XXXXXXXX",
            databaseURL: "XXXXXXXX",
            projectId: "XXXXXXXX",
            storageBucket: "XXXXXXXX",
            messagingSenderId: "XXXXXXXX",
            appId: "XXXXXXXX"
        };
```

この部分はFirebaseプロジェクトからコピーして置換してください。
![key.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199678/d4cc0190-2f14-e077-98e7-b6b78c348a08.png)

あとはWebサーバを立ち上げるだけ。

index.htmlを保存したディレクトリに移動し、

```bash
$ ruby -run -e httpd . -p 8000
```

Webブラウザでlocalhost:8000にアクセスします。

# 完成図

未ログイン時
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199678/411b5241-9555-6119-c804-f336d18c6eb6.png" width="300">

ログイン時
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/199678/54db3091-df9e-e92c-e410-2112c977b8e7.png" width="300">

# 次回予告

Firebase Authentication単独では、名前、メールアドレス、パスワードぐらいの情報しか保存できません。
その他のユーザー情報はFirebaseに含まれるNoSQLサービスであるFirestoreを使うのが一般的なので、次回はFirestoreとの連携記事を書きます。