Firebase Authenticationの認証でCloudflareを利用してFirebase Hostingへのカスタムドメイン登録を省略する

## はじめに

Firebase Authenticationで認証を組み込むとき、何も設定しないとFirebaseのデフォルトのドメインになってしまう（以下はGoogleの場合）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/8232bd20-5a38-30b2-5460-186c9bb4f28d.png)

これだとカスタムドメインを利用してサイトを構築していても、認証後のリダイレクト先とみているサイトのドメインがちぐはぐでユーザーからするとかなり混乱する。

というわけでこの`authDomain`もカスタムドメインにしたいと思うだろう。今回はカスタムドメインの管理をCloudflareで行っている（ネームサーバがCloudflareである）場合に、[Google ログインのリダイレクト ドメインのカスタマイズ](https://firebase.google.com/docs/auth/web/google-signin?hl=ja#customizing-the-redirect-domain-for-google-sign-in)に書かれている方法とは少し違った方法でも、要件を実現できるのでそれをやってみたいと思う。

## やってみる

認証後のリダイレクト先となるカスタムドメインに対するCNAMEレコードを以下のように設定する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/71548ec3-f7c2-c7f5-9098-f2cc84dbeaf9.png)

これで元々Firebase AuthenticationのauthDomainである`****.firebaseapp.com`に対して`auth.<カスタムドメイン>`というエイリアスが設定される。

あとは、[Google ログインのリダイレクト ドメインのカスタマイズ](https://firebase.google.com/docs/auth/web/google-signin?hl=ja#customizing-the-redirect-domain-for-google-sign-in)に書かれている通りに以下を行う。

- 認可済みドメインのリストにカスタムドメインを追加
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/e1491668-f477-2a91-1a45-33b9d98e9a92.png)
- OAuth設定ページで、リダイレクトページの URL（https://auth.custom.domain.com/__/auth/handler ）を許可リストに登録
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/6c6b6eb7-505e-be79-140f-e4f9d3454cf0.png)
- authDomainにカスタムドメインを指定
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/a1a2c2be-5a51-b638-c691-119d9f9dce72.png)

ここまで完了すると、以下のように認証時のGoogleへの認証リクエストのURIが以下のようにカスタムドメインのものになり、また認証画面でリダイレクト先に表示されるドメインもカスタムドメインになる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/477db5a8-6c11-c044-7ddd-509958904a72.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/f0f57882-1a95-e563-deec-db1b2f945a0a.png)

## なぜFirebase Hostingの設定なしでも認証後のリダイレクトをカスタムドメインにできるか？

まず、HTTPS通信についての予備知識が必要になるので、それについて話をしたいと思う。

HTTPSはSSL/TLSによる暗号通信のことだが、TLSハンドシェイクと呼ばれるやり取りをして暗号通信を確立する。TLSハンドシェイクの詳細は省くが、今回の話で重要なポイントとしてサーバ証明書がTLSハンドシェイクをする際には必須であるという事。
つまり、ブラウザからサーバへリクエストを送る際には、そのサーバが信頼できるか？という確認が必ず行われ、この信頼性の確認のためにサーバ証明が必要になる。

仮にカスタムドメインを利用したいとなった時は、DNSのCNAMEレコードでエイリアスにする。この時、DNSは名前解決の仕組みなので、`auth.example.com`をブラウザに打ち込んでリクエストを送る際に、`auth.example.com`は`****.firebaseapp.com`ですね、そこにアクセスしてくださいとしか教えてくれない（正確には少し名前解決の手順の説明としては違うが、今回の説明の趣旨ではこの理解で十分）。

DNSに教えてもらった通り、`****.firebaseapp.com`のサーバにリクエストが届いて、サーバ証明書をもらうが、この時、`****.firebaseapp.com`は自身のドメイン`firebaseapp.com`であることを証明するサーバ証明書しか持っていない。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/a2f9ffed-46ea-7db8-c138-5737862a0720.png)

ので、ブラウザからすると、`auth.example.com`なのに`firebaseapp.com`の証明書が来たぞ、これはおかしい！となる。なのでChromeであれば以下のような警告が表示される。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/7cc4e1a8-7b0d-f37c-5576-82c0d0abea92.png)

そこで`auth.example.com`に対するサーバ証明書が必要になるが、Firebase Hostingではこの証明書を発行してくれる仕組みがある。それが[Google ログインのリダイレクト ドメインのカスタマイズ](https://firebase.google.com/docs/auth/web/google-signin?hl=ja#customizing-the-redirect-domain-for-google-sign-in)の手順の一番最初の`Hosting 用にドメインを設定する`の手順。
この手順ではドメインの所有確認をしてそれに問題がなければ、`auth.example.com`に対するサーバ証明書を代理で発行してくれる。そしてそれをブラウザからのリクエスト時に返すことで問題なく通信できるようになっている。

実際にFirebase Hostingでカスタムドメインを設定すると、以下のようにGoogleの認証局から証明書が発行されていることが確認できる（https://www.sslshopper.com/ssl-checker.html というサイトでは以下のような内容が確認できる）。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/05a51cf0-ab30-c250-030d-7a9edafd4b90.png)

前置きが長くなったが、つまり、証明書さえちゃんと発行できれば問題ないという事。
CloudflareのDNSの設定で`プロキシ済み`を選ぶと、トラフィックが、ブラウザ→CloudflareのCDN→オリジンサーバ、という経路になる。そして`auth.example.com`に対する証明書はCloudflareが発行してくれるので、これをブラウザ側は受け取り信頼できると判断できるようになる（詳細は[Proxy status](https://developers.cloudflare.com/dns/manage-dns-records/reference/proxied-dns-records/)も参照）。

したがって、CloudflareのDNS設定で`プロキシ済み`の設定をすれば、別にFirebase Hostingの設定は不要になる。Firebaseで認証をする際に証明書を確認してみると、以下のようにちゃんと証明書が発行されていることが確認できる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1372684/f75534b4-41e3-20c4-f19c-a34f7eb5fd43.png)

※上記ではFirebaseのドメインについて、サーバという言い方をしたが、正確にはFirebaseの運営元のGoogleのCDNがリクエストを受けていて、CDNから（エッジ）証明書が送られてきているはず。そのことは（[カスタム ドメインを接続する](https://firebase.google.com/docs/hosting/custom-domain?hl=ja)の図からもわかり、例えば`auth.example.com`にリクエストしたとき、名前解決されて`****.firebaseapp.com`にリクエストが行くが、これを受けているのはオリジンサーバではなくCDN（図でも証明書をCDNに配置すると書かれているのはそういう事）。

## まとめとして

今回はCloudflareを利用することで、Firebase Hostingでのカスタムドメインに対する証明書の発行を省略するという事をやってみた。別にFirebase Hostingで証明書を発行してもらう方法でも問題はなく、ドキュメント的にはその方法なので、Cloudflareの方法を採用するかは好みの問題になると思う。