FirebaseでBasic認証をかけてサイトを作る(Hostingする)

## Firebaseで簡易サーバをたてたい

Firebaseが便利だと聞いたので、さくっとWebページのホスティングがしてみたい。
でもあんまり変なページは公開したくないので、できれば、Basic認証くらいかけたい。
できればWindowsでやりたい。

というときの手順のまとめ。

## どのプロンプトを使うか？

`Powershell`でいきます。
以降`Powershell`上で実行してください。

> Macだと悩むことないのですがWindowsだといつも悩む、何のコンソールを使うか？問題です。 最初は、Migw(Git-bash)でやろうとしたのですが、いろいろとスムーズにいかないところがあって、試行錯誤の結果 `Powershell` になりました。

## Firebaseのアカウント作成からサイト上での準備

Googleアカウントをとって、Firebaseのサイトにアクセスすれば、それほど悩まずにFireabaseのログインはできると思います。

その後トップページの**プロジェクトの追加**から、プロジェクトを作ります。

プロジェクト名に適当な名前をいれて、規約を読んでからGoogleのデータ共有などのチェックを付けたり/外したりして、プロジェクトの作成を行います。

> 個人的には、この手のチェックは ON でいいと思います。
> Googleなどに価値ある情報を提供して、Googleが良いサービスを作ってくれたらソフトウェア業界の進歩につながるので、１エンジニアとしては統計的情報の提供くらいなら喜んでさしあげます。

## FirebaseセットアップからDeployまで

Firebaseのサイトの手順などを見ていくと、`npm` のコマンド等がでてきますのでそれにしたがってやれば良いだけです。と言いつつ、つまづくところがあるので下記順に見ていきます。

まず、`firebase`コマンドを使えるようにするため`firebase-tools`をインストールします。
ここはあまり問題ないと思います。

```powershell
> npm install -g firebase-tools
```

次にFirebaseへのログインをします。
ここでもし会社の環境などでProxyを使っているならProxyの設定をしておきましょう。
Powershellを使って環境変数の設定を行います。

```powershell
> $Env:https_proxy = "http://xxxx"
> $Env:https_proxy = "http://xxxx"
```

次にログインをします。

```powershell
> firebase login
```

何か聞かれますが Enter で切るぬけると、ブラウザが立ち上がって、場合によってはGoogleのログイン画面などが出てきます。
さらに場合によっては、ハッシュみたいな文字列が出てくるので、それをコピーしてPowershell上に張り付けします。 出なかったらいいです。
これでログインできた状態になってくれます。

> ここがMingw(Git-bash)の場合だと色々エラーがでたり、Proxy未設定の場合にエラーがでたり、と山場になりますが、Powershell使って行えば意外とスムーズにいってしまいます。 わたしはここで丸1日つぶしました；；

次に初期設定をします。

単なるHosting、つまりは、Webサーバーであれば`Hosting`として初期設定を行いますが、今回はBasic認証をかけたいがために`Functions`も追加したプロジェクトを作ります。

`Functions`として作って`Node.js Express`からBasic認証をかけるという作戦です。

ではさっそく。

```powershell
> firebase init
```

を実行すると、コンソール上でメニューが出てきます。

```powershell
ExperimentalWarning: The fs.promises API is experimental

     ######## #### ########  ######## ########     ###     ######  ########
     ##        ##  ##     ## ##       ##     ##  ##   ##  ##       ##
     ######    ##  ########  ######   ########  #########  ######  ######
     ##        ##  ##    ##  ##       ##     ## ##     ##       ## ##
     ##       #### ##     ## ######## ########  ##     ##  ######  ########

 ...中略...

>( ) Database: Deploy Firebase Realtime Database Rules
 ( ) Firestore: Deploy rules and create indexes for Firestore
 (*) Functions: Configure and deploy Cloud Functions
 (*) Hosting: Configure and deploy Firebase Hosting sites
 ( ) Storage: Deploy Cloud Storage security rules
```

このメニューが出てきたらカーソル上下で選んで、**スペースキー**で`Hosting`と`Functions`にチェックをつけてからEnterを押します。
いくつか質問されますが基本はデフォルトのままで大丈夫です。

プロジェクトを聞かれる選択肢がありますが、最初の手順でFirebaseのサイト上で作ったプロジェクトが出てくるはずなので、それを選択しておきます。

> JavaScriptかTypescriptか聞かれるところもありますが、今回の記事ではJavaScriptを使ってます。Typescriptを使いたい場合はそちらを選択して、サンプルコードも読み変えてください。

このあとしばらくするとプロジェクトのファイル一式が作られます。
こんな感じのファイル構成になっていると思います。

```
functions/
public/
.firebaserc
.gitignore
firebase.json
```

## Basic認証をかけつつ静的ファイルのHostingを行う

まず通常の`Hosting`でファイルが認証なしでホスティングされないように`public`の下のファイルを消してしまいます。フォルダは残しておいてください。

次に、`functions/index.js` を下記のように書き換えます。

```javascript
const functions = require('firebase-functions')
const express = require('express')
const basicAuth = require('basic-auth-connect')

const app = express()

app.all('/*', basicAuth(function(user, password) {
  return user === 'hoge' && password === 'hogehoge';
}));

app.use(express.static(__dirname + '/static/'))

exports.app = functions.https.onRequest(app)
```

簡単にいってしまうと、すべてのリクエストに対して`basicAuth`を適用して認証を行うようにしてから、`./static/`の静的ファイルのホスティングを行うようにしています。
上記の例だと、IDは`hoge`で、パスワードは`hogehoge`になりますので、適宜書き換えてください。

次に、実際にホスティングしたいファイルを置きます。
今回は楽がしたいので`functions`の下に`static`というフォルダを作って置いてしまいます。

```
functions/
  +- static/ ←ここ
      +- index.html
      +- index2.html
public/
.firebaserc
.gitignore
firebase.json
```

こんな感じで作ってみます。
内容はなんでもいいのですがこんな感じで作ってみました。

```html:index.html
I am index.html.
```

```html:index2.html
I am index2.html.
```

次にルーティング的なものを設定します。
デフォルト作られたものに対して`rewrites`を足します。すべてのリクエストを`app`という`Functions`の機能にリダイレクトする設定です。

```json:firebase.json
{
  "hosting": {
    "public": "public",
    "rewrites": [
      {
        "source": "**",
        "function": "app"
      }
    ],
    "ignore": [
      "firebase.json",
      "**/.*",
      "**/node_modules/**"
    ]
  }
}
```

準備は完了したのでついにデプロイです。
じゃなかったです。

Basic認証用にFunctionsにいろいろとライブラリを足したので`npm install`が必要です。
`functions`フォルダに`cd`してから、必要なライブラリを`npm install`します。
デプロイ作業のため、忘れないようにカレントフォルダも`cd ..`で戻しておきます。

```powershell
> cd functions
> npm install --save express
> npm install --save basic-auth-connect
> cd ..
```

そしてやっとデプロイです。

```powershell
> firebase deploy
```

エラーがなければすんなりとデプロイされるはずです。

**Deploy complete!**

## 確認

Firebaseのサイトのコンソール上からURLが確認できます。
メニューの`Hosting`あたりから見れます。

アクセスすると無事に認証が動きIDとパスワードがきかれるはずです。
コードで書いた通り `hoge` `hogehoge` を入れるとブラウザ上には `I am index.html. ` が表示されるはずです。

念のため `https://......../index2.html` と直指定でURLを入れた場合も確認してみますが、無事に認証がかかってファイルがみれると思います。※上で認証済みならプライベートウィンドウなどひらいて確認してみてください。

## まとめ

ということで無事にBasic認証をかけてのHostingが出来ました。
大きな流れで言うと、

1. Firebaseを普通にHosting + Functionsで設定をする
2. Hostingのファイルを空にする
3. Functions(≒Express)ですべてのアクセスにBasic認証をかける
4. Functions(≒Express)で独自の静的ファイルのホスティングを行う

という流れになって、無事に実現ができました。

## 謝辞

この記事を書くために(じゃないですが)、"デカビタC(缶)"と"たけのこの里"を残して言ってくれた同僚に感謝です。
m__m