firebase authのユーザー情報からトークン情報を取り出す簡単なスクリプトをnodeでつくる


## モチベーション

最近は、クライアント（iOSやAndroid, Webクライント）とAPIサーバを別立てして開発していくことは多いと思います。

弊社も例にもれず、こういった構成で開発をしています。

なおAPIサーバのユーザー認証は、firebaseのトークンをJWT認証することで実現しています。
ただし、下記の理由でトークンの扱いが多少面倒なので、今回スクリプトを書いて解消したいと思います。


* APIサーバをRuby on Railsで開発している。しかし、firebaseはRuby向けのSDKを公開していない（2020年7月時点）。
  * [Libraries - Firebase - Google](https://firebase.google.com/docs/libraries)
* firebaseのトークンは1時間で有効期限がくる

## ゴール
* nodejs経由でfirebaseにアクセスし、トークンを取り出す処理をコンソールアプリを作成する

正直言語はなんでも良いのです。
今季は、SDKが豊富に用意されている、コンソールアプリを作りやすい、という理由でnodejsを選択しています。

## 環境

* macOS Mojave Version10.14.4
* nodejs v12.13.0
* npm 6.14.5

※ Windows環境では未検証

## 前提

* javascriptの基本知識がある
* node, npmの基礎知識がある
* firebase consoleでユーザ作成されている

## スクリプト
### 1. 事前準備① firebaseの認証情報を取得する

firebase consoleにアクセスし、nodejsからfirebaseへ接続するための認証情報を取得します。

#### 1.1. firebase consoleにアクセス
![Pasted_Image_2020_07_15_9_29.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37873/2f21ff3e-ff2f-0ba2-a985-a84eb88c6d30.png "Pasted_Image_2020_07_15_9_29.png")

#### 1.2. 認証情報をコピー

設定 > 全般 > マイアプリ > ウェブアプリ を選択。
`firebaseConfig`部分をコピーして控えておきます。

![Pasted_Image_2020_07_15_9_31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37873/6a0a71a9-78c7-5411-b449-c46dee31c014.png "Pasted_Image_2020_07_15_9_31.png")

### 2. 事前準備② nodeプロジェクトの作成
#### 2.1. nodeプロジェクトの作成

適当なフォルダを作成する。

```bash
mkdir firebase_authentication
cd firebase_authentication

# npm initの質問は、何も考えずEnterでOK
npm init 
```

`package.json` が作成されていればOKです。

```bash
~/firebase_authentication❯ ls
total 8
drwxr-xr-x    3 TomoakiTANAKA  staff    96 Jul 15 09:42 .
drwxr-xr-x+ 164 TomoakiTANAKA  staff  5248 Jul 15 09:43 ..
-rw-r--r--    1 TomoakiTANAKA  staff   219 Jul 15 09:42 package.json
```

#### 2.2. firebaseSDKのインストール

```bash
npm install firebase
```

`package.json` にfirebaseが追加されます。

```json:package.json
+  "dependencies": {
+    "firebase": "^7.16.0"
+  }
```

### 3. スクリプト作成

```bash
mkdir scripts
cd scripts
touch firebase_token.js
```

```javascript:firebase_token.js
const firebase = require('firebase/app');
const firebaseAuth = require('firebase/auth');
const readline = require('readline').createInterface({
  input: process.stdin,
  output: process.stdout
});

// firebase consoleから取得した認証情報
const firebaseConfig = {
  apiKey: "AIzaS.....",
  authDomain: "hogehoge-foobar.firebaseapp.com",
  databaseURL: "https://hogehoge-foobar.firebaseio.com",
  projectId: "hogehoge-foobar",
  storageBucket: "hogehoge-foobar.appspot.com",
  messagingSenderId: "532........",
  appId: "1:532.......:web:xxxxxxxxxxxxxxx",
  measurementId: "G-xxxxxxxxxxx"
};

// 認証したいメールアドレス
const email = 'hogehoge@eversense.co.jp';

// パスワードの読み込み
readline.question(`input ${email}'s password:`, (password) => {
  showFirebaseIdToken(email, password);
  readline.close();
});

// firebaseにアクセスしトークンを取得、表示する
function showFirebaseIdToken(email, password) {
  // firebase appの初期化
  const app = firebase.initializeApp(firebaseConfig);

  // メール認証
  firebase.auth().signInWithEmailAndPassword(email, password)
    .then((result) => {
      const firebaseAuthUser = result.user;
      firebaseAuthUser.getIdToken(true)
        .then((idToken) => {
          console.log(idToken);
        })
        .catch((error) => {
          console.log(error);
        });
    })
    .catch(function (error) {
      console.log(error);
    });

}
```

実行方法

```bash
node scripts/firebase_token.js
```

## まとめ

今までログに認証情報を吐き出して、コピペして…というイケてないフローでしたが、これでだいぶ開発体験が向上しました。
あと、記事作成中に、`firebase CLI`使えばいんじゃね？と思いました。

まぁnodeベースでかければちょっとした処理を試せるので、これはこれでいいかなと思います。