Vue.jsでSPA - [16] へー、FirebaseでWebアプリのログインってこうやるのか

# はじめに

だいぶ今更感があるのですが、Vue.js で Firebaseの認証をやってみました

# つくってみたのはこんな感じ[^3]

モバイルサイズですがWebアプリです。コードは下の方に貼っておきます

![out12.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32540/88f2370d-8acc-e1c4-4eaf-91735fffe182.gif)



# やってみたこと

以下のような手順で、調べながらやりました

## Firebase SDK を Web アプリに読み込んでおく

[公式](https://support.google.com/firebase/answer/7015592?hl=ja)のとおりに事前設定。要はこんなやつを `html` に貼り付けるアレ

```javascript

var firebaseConfig = {
  apiKey: "api-key",
  authDomain: "project-id.firebaseapp.com",
  databaseURL: "https://project-id.firebaseio.com",
  projectId: "project-id",
  storageBucket: "project-id.appspot.com",
  messagingSenderId: "sender-id",
  appID: "app-id",
};
```

## Firebase で Authentication を有効にしておく
今回は一番シンプルそうな「メール / パスワード」での認証を有効化[^1]

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32540/ea3bf92a-b85d-2798-e20f-64a4231b2d8c.png)


## 公式のサンプルコードで動作確認

この[ログインのサンプルコード](https://github.com/firebase/quickstart-js/blob/f76b14ca00cca48dbfca5c787c0a4ca73eb9857d/auth/email-password.html)をありがたく使わせてもらいました。[公式のここ](https://firebase.google.com/docs/auth/web/start?hl=ja)から辿ることができます。見ての通り、ログインにまつわる一通りの動作が実装されています。パスワードリセットなんかも。使ってみると、ボタンの下の `null` のところにバックエンドとのやりとりが表示されるのでわかりやすくてよい

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32540/fb270d37-9391-68d4-6018-636f30c03eba.png)

試しにこのサンプルコードで `SIGN UP` したユーザはこんな感じでFirebaseコンソールでみることができる

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/32540/0a43d4a8-4f3e-a4c7-3aba-88d4aed8904c.png)

## サンプルをみながら自分のコードで認証できるようにする

サンプルをみながら Vue.js で書いてみました。簡単なんでペタッと貼っておきます。

```html

<!DOCTYPE html>
<html lang="en">
<head>
  <!-- Basic Page Needs -->
  <meta charset="utf-8">
  <title>KUSA</title>
  <meta name="description" content="">
  <meta name="author" content="">
  <!-- Mobile Specific Metas -->
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <!-- FONT -->
  <link href="//fonts.googleapis.com/css?family=Raleway:400,300,600" rel="stylesheet" type="text/css">
  <!-- CSS -->
  <link rel="stylesheet" href="css/normalize.css">
  <link rel="stylesheet" href="css/skeleton.css">
  <!-- Favicon -->
  <link rel="icon" type="image/png" href="img/kusa-h40.png">
  <!-- Application configuration -->
  <script type="text/javascript" src=".app_config.js"></script>
  <!-- Fontawsome -->
  <script src="https://kit.fontawesome.com/a1763a7d6f.js" crossorigin="anonymous"></script>
  <!-- Vue.js -->
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>

<body>

<div id="app">

<!-- Menu -->
<div class="container" style="margin-top: 20%">
  <p style="text-align: center;"><img src="img/kusa-h60.png"></img></p>
  <input v-model="email" class="u-full-width font-awesome" type="email" placeholder="Email">
  <input v-model="password" class="u-full-width font-awesome" type="password" placeholder="Password">
  <input @click="signIn" class="u-full-width button-primary" type="submit" value="login">
  <input @click="signUp" class="u-full-width" type="submit" value="create account">

  <a href="#" style="text-decoration:none" @click="signOut">Logout</a>
  <a href="#" style="text-decoration:none" class="u-pull-right">Forgot password</a>

  <label style="margin-top: 20px">Error :</label>
  <pre style="margin-top: 0px; margin-bottom: 5px;"><code>{{ message }}</code></pre>
  <label>Current user :</label>
  <pre style="margin-top: 0px; margin-bottom: 5px;"><code>{{ currentUser }}</code></pre>
</div>

</div>

<!-- Insert this script at the bottom of the HTML, but before you use any Firebase services -->
<!-- Add the entire Firebase JavaScript SDK. Replace when go for production -->
<script src="https://www.gstatic.com/firebasejs/6.2.0/firebase.js"></script>

<script>

  firebase.initializeApp(conf.fbc);
  //firebase.analytics();

  // Vue
  var app = new Vue({
    el: '#app',
    data () {
      return {
        email: '',
        password: '',
        message: '',
        currentUser: ''
      }
    },
    methods: {
      signIn: function () {
        app.message = ''; console.log('sign-in pressed');

        firebase.auth().signInWithEmailAndPassword(app.email, app.password).catch(function(error) {
          var errorCode = error.code;
          var errorMessage = error.message;

          app.message = error.message;
          console.log(error.message);

        }).then(function() {
          app.currentUser = firebase.auth().currentUser;
        });
      },
      signUp: function () {
        app.message = ''; console.log('sign-up pressed');
        firebase.auth().createUserWithEmailAndPassword(this.email, this.password).catch(function(error) {
          var errorCode = error.code;
          var errorMessage = error.message;

          app.message = error.message;
          console.log(error);
        }).then(function() {
          app.currentUser = firebase.auth().currentUser;
        });
      },
      signOut: function () {
        firebase.auth().signOut().then(function() {
          app.currentUser = firebase.auth().currentUser;
        });
      },
      resetPass: function () {
　　　　　// あとで書く
      }
    }
  })
</script>

</body>
</html>

```
- `firebaseConfig` は直書きしたくなかったので外部ファイル `.app_config.js` から呼ぶようにして、`.app_config.js` は `gitignore` しています[^2]
- ログインしているかどうか、誰でログインしているかは `firebase.auth().currentUser` に聞けばわかるので便利

# これから

Firebase SDK はよくできていて、かなり短時間で認証周りが作れることがわかりました。あとで OAuth 系も触ってみます。そのあと、引き続き、この KUSA アプリ完成までやっていきます！

# シリーズ
- [Vue.jsでSPA - [1] Element UIでベースの画面をつくる](https://qiita.com/narutaro/items/50d0e4714f93279502c9)
- [Vue.jsでSPA - [2] Element UIで各ペインの画面をつくる](https://qiita.com/narutaro/items/9abbf7881f692c985484)
- [Vue.jsでSPA - [3] vue-routerでルーティング ](https://qiita.com/narutaro/items/74178f4ea031b0ccfa44)
- [Vue.jsでSPA - [4] コンポーネントにしてみる ](https://qiita.com/narutaro/items/df793bb34129d113d9f2)
- [Vue.jsでSPA - [5] リアクティブになってる？](https://qiita.com/narutaro/items/bed4eab6e53e3b46c0b2)
- [Vue.jsでSPA - [6] サーバからのデータ取得](https://qiita.com/narutaro/items/82f4d9635c398524431c)
- [Vue.jsでSPA - [7] Vueからサーバデータ取得](https://qiita.com/narutaro/items/91da194788318c226e0e)
- [Vue.jsでSPA - [8] バックエンドとうまくやっていこうとして試したこと](https://qiita.com/narutaro/items/3b7135eed8f6e930a0e6)
- [Vue.jsでSPA - [9] 今更ながらCORSとそのエラーの回避方法](https://qiita.com/narutaro/items/26e4cbec386bc054bbd7)
- [Vue.jsでSPA - [10] Safari..お前か...3rd party cookie](https://qiita.com/narutaro/items/e53f653d73a6934046d0)
- [Vue.jsでSPA - [11] Element UIでログイン画面](https://qiita.com/narutaro/items/010009c0198371fee658)
- [Vue.jsでSPA - [12] ログイン：シングルペインからツーペインへ画面遷移](https://qiita.com/narutaro/items/fca953b3b2ed5c63360c)
- [Vue.jsでSPA - [13] モバイル向けに OnsenUI に手をだす](https://qiita.com/narutaro/items/bdc0e25c22369466bed3)
- [Vue.jsでSPA - [14] Vue.jsとOnsenUIを使ったオレオレなショッピングカートチュートリアル](https://qiita.com/narutaro/items/9502b90b565366911c57)
- [Vue.jsでSPA - [15] 世界中の人とミーティング時間を決める時に便利なやつ](https://qiita.com/narutaro/items/d6431f54050504bf1551)
- [Vue.jsでSPA - [16] へー、FirebaseでWebアプリのログインってこうやるのか](https://qiita.com/narutaro/items/3c37fe6c3b19a6143a07)

[^1]: 有効になってないと、サンプルコードにこんな風に怒られる → `The given sign-in provider is disabled for this Firebase project. Enable it in the Firebase console, under the sign-in method tab of the Auth section.`
[^2]: 直書きしてもセキュリティ上問題ないし、本番に出すときに Firebase Hosting つかうと、どうせバレるところに設定ファイルがあるようですが、やはり開発中はデータベースなどのエンドポイント知られるのはなんか気になるし、デバッグでルールをフルオープンしたりもあるので念のためこうしてます
[^3]: ffmpeg で mov を gif にしたけど、なんか青っぽい。なんとかならんか