ElectronでFirebaseAuthを利用する

ElectronでFirebaseAuthを利用するにはいくつか問題があります。

まず、大前提としてFirebase公式はElectronへのサポートを提供していない事を理解しておきましょう。

その他にも、Electronは通常fileプロトコルでアプリケーションを動かす事が多いですが、その状態でFirebaseAuth(もっというとGoogleAPIなど)を利用しようとしても
`対応してるプロトコルはhttpかhttps、もしくはChromeExtensionで、その他にWebストレージを有効にする必要があります。`
と怒られます。

今回利用したいのはFirebaseAuth(Googleアカウント認証/認可)のみですが、FirebaseのリアルタイムDBやFirestoreでも同じように対応することで利用出来ると思います、ただし検証はしていないのでAuth以外を使う方はあくまで参考程度にしてください。

---

Electronアプリが既に存在する前提で話を進めていきます。

## ElectronアプリにExpressモジュールを追加してローカルサーバーを建てる

httpモジュール使えば新規にExpressモジュールを追加する必要はありませんが、簡単なのでExpressをインストールします。

また、既にElectronアプリがhttp/httpsで読み込んでいる場合はこの章はスキップできます。

Electronアプリのディレクトリで以下を実行し、Expressを追加します。

`% npm i express`

インストールが完了したら、Electronのエントリーポイントとなるファイル、通常はアプリディレクトリにあるmain.js、にExpressでサーバーを建てるためのプログラムを追加します。

```javascript:main.js
const express = require('express');
const exp = express();
exp.use(express.static('./'));
exp.listen(8080);
```

ポートは任意の開いてる所を選んでください。

このコードを書くことでElectronアプリにブラウザからも`localhost:8080`でアクセスできるようになります。

main.jsの中のファイルをロードしている部分を以下のように書き換えましょう。

```javascript:main.js
//win.loadFile('index.html');            //筆者はこのようにファイルを読み込んでいた
win.loadURL('http://localhost:8080');    //このようにlocalhost:8080を読むように変更する
```

`% electron .`コマンドでアプリを起動すると、fileを読んでいた時と同じように画面が表示されるはずです。

## Firebaseのセットアップ

プロジェクトは事前に作成し、GoogleAuthを有効にしておいてください。

アプリケーションにFirebaseモジュールを追加しましょう。

既に追加している方はスキップしてください。

`% npm i firebase`

基本的に、モジュールを追加した後にアプリで利用するには以下のコード

```javascript
const firebase = require('firebase');
```

を記述しますが、今回は無視してください。書かなくても問題無いです。

インストールしたら、index.htmlのheadに以下のコードを追加します。

```html:index.html
<script src="./node_modules/firebase/firebase.js"></script>
<script src="./node_modules/firebase/firebase-app.js"></script>
<script src="./node_modules/firebase/firebase-auth.js"></script>
```

これにより、JavaScriptファイル内でrequireからインポートしなくても、firebaseオブジェクトが利用できるようになります。

## FirebaseAuth部分の処理を書く

筆者の環境は、自分で設置したbutton要素をクリックすると、ログイン処理が走るようになっているので、その前提で進めて行きます。

```html
<button id="google_auth">Googleログイン</button>
```

```javascript:login.js
const authButton = document.getElementById("auth_button");
authButton.addEventListener("click", () => {auth()}, false);
```

上記のように、Googleログインボタンをクリックすると、authという関数が呼ばれます。

まずauth関数の前に、firebaseオブジェクトを利用するには、初期化処理が必要です。

初期化に必要な情報はFirebaseプロジェクトの設定から確認できるので、自身の情報に置き換えて読んでください。

```javascript:login.js
const firebaseConfig = {
    apiKey: "xxx",
    authDomain: "xxx",
    databaseURL: "xxx",
    projectId: "xxx",
    storageBucket: "xxx",
    messagingSenderId: "xxx",
    appId: "xxx"
};
firebase.initializeApp(firebaseConfig);
```

これでfirebaseオブジェクトが利用可能になるので、authの実装をしていきます。

```javascript:login.js
const auth = async () => {
    const provider = new firebase.auth.GoogleAuthProvider();
    const auth = await firebase.auth().signInWithPopup(provider);
    if (auth.user != null && auth.user.email != null) {
        console.table({uid: auth.user.uid, email: auth.user.email});
    }
};
```

これで準備がほぼ整いました。

筆者は認証に`signInWithPopup()`を使用しています。

Electronアプリでこのようにポップアップを利用するには、main.js内でインスタンス化されているBrowserWindowに値が`true`な`webPreferences.nativeWindowOpen`プロパティを渡す必要があります。

```javascript:main.js
let win;
function createWindow () {
    win = new BrowserWindow({
        width: 1200,
        height: 1000,
        webPreferences: {
            nativeWindowOpen: true, //ここ
            nodeIntegration: true
        }
    });

    win.loadURL('http://localhost:8080');

    win.webContents.openDevTools();

    win.on('closed', () => {
        win = null;
    });
}
app.on('ready', createWindow);
```

ここまでやって、ついに準備が整いました。

Electronアプリを起動して、「Googleログイン」ボタンをクリックすると、ポップアップウィンドウが表示され、馴染み深いGoogleログイン画面が表示されます。

ログインを終えると、ポップアップウィンドウが閉じられ、開発者ツールのコンソール画面にユーザーIDとログインしたユーザーのメールアドレスが表示されます。

お疲れさまでした。