ServiceWorkerでFirebaseAuthenticationのセッション管理
FirebaseAuthenticationを最近触っている。
とても便利。便利通り越して感動。
もうこれなしでは、生きていけない体になってしまった。
そんなFirebaseAuthenticationをSSRモードのnuxtで利用しようとした時、
セッション管理でハマったので、自分の理解としてまとめる。
nuxtServerInitでログイン判定を行いたい
SSRで作成しているので、当然 nuxtServerInit でログイン判定を行いたい。
firebaseでログインしていたら、nuxtServerInitでstoreにuidなりidTokenなり、投げたくなるのが人の性ってもんじゃないですか。
だけど、firebaseの認証情報はIndexedDBに保存されるので、
nuxtServerInitの時点では認証情報は取得できない。
取得できないということは、ログイン判定が行えない。
ログイン判定が行えないということは、絶望するしかない。悲しい。
cookieにIDTokenを保存する?
cookieはserverにも投げられるので、IDTokenをcookieに保存すれば
nuxtServerInitでも受け取れるぞ。
それはそうなんだけれど、firebaseのIDTokenは有効期限が1時間。
すぐに有効期限が切れてしまうし、有効期限が切れた時、
IDTokenをrefreshするためのRefreshTokenまでcookieに入れるとかしたくない。
というか、IDTokenのrefreshは、そもそもSDKが隠蔽している箇所だから、
自分ではやりたくない。というかできない。
nuxtServerInitで、SDK使わずに、IDTokenが有効かどうか、無効だったらrefreshして、とか無理ゲーである。
ServiceWorkerでセッションを管理する
やっと本題。
ていうか、ここまでのこと、ぜーんぶ公式のドキュメントにちゃんと書いてあるんだけどね。
すごい。ありがとう。Firebaseのドキュメントを作ってくれている人!読解力が無くてごめんなさい!
さて、ServiceWorker。名前は聞いたことはあったけど、使ったことはないので調べてみる。
・ブラウザにインストールして使用する
・インストールされたServiceWorkerは別スレッドでJSを動かすことができる
・ServiceWorkerからIndexedDBにアクセスできる
・ServiceWorkerにはライフサイクルがある
という、ざっくりとした理解。
じゃあ、次はFirebaseのドキュメントを読み解く。
アプリに対するフェッチ リクエストはすべてインターセプトされ、使用可能であれば ID トークンがヘッダーを介してリクエストに追加されます。サーバー側では、リクエスト ヘッダーに ID トークンがあるかどうか確認され、検証後に処理されます。Service Worker スクリプトで、フェッチ リクエストがインターセプトされ、変更されます。
なるほどわからん。というか盛大に勘違い。
フェッチリクエストと書いてあるので、
nuxtから外部APIを叩くときのフェッチをインターセプトするのかと思っていた。
いやいや、僕がやりたいことは、nuxtServerInitでIDTokenを受け取りたいだけであって、外部APIは関係ないのですよ。一体何がしたいんだServiceWorkerさん。
と、すべての責任をServiceWorkerになすりつけていたのだけど、
実際に試してみると、このフェッチのインターセプトは、
nuxtに対するリクエストをインターセプトするということだった。
つまり、流れとしては、
1. ページに初めて訪れたときにServiceWorkerがインストールされる
2. 以降のnuxtに対するリクエストは、ServiceWorkerによりインターセプトされる(nuxtに到達する前にServiceWorkerの処理が走る)
3. インターセプトした処理の中で、Firebase SDKを通しIDTokenを取得する(この時、ServiceWorkerからはIndexedDBにアクセスできるので、認証情報にも当然アクセスできる。IDTokenの有効期限も更新される。)
4. 取得したIDTokenを、リクエストヘッダに追加する
5. IDTokenを追加したリクエストヘッダで、nuxtへ流す
6. nuxtに到達し、nuxtServerInitが呼び出される
7. リクエストヘッダには4で追加されたIDTokenが含まれているので煮るなり焼くなり好きにする
ということだと、理解した。は〜、難しい。
細かい実装については、下記によくまとまっていたので割愛。
大変助かりました。ありがとうございます。
この記事が気に入ったらサポートをしてみませんか?