Firebase Node.js Client SDKだけでAuthenticateを行いたい
モチベーションとしては
- ブラウザ側にfirebaseを意識させたくない
- ブラウザにバンドルしたくない
と言ったところ。
Next.jsのカスタムサーバーでやる or API Routeでやるのを想定してやってみる。
今回は普通にメアドとパスワードでログインではなく、メアドだけでログインさせたい(magic link login)
ブラウザには window.NEXT_DATA かhttpOnlyではないcookieを書き込んでloggedIn: booleanみたいな形で認証してるのかどうかだけを渡してあげるようにする。
最初にすべきはログインだが、UI上でメールアドレスをinputにいれてもらってsubmitする。この時 /api/signin/emailなどに向かってメールアドレスをpostする。そのあと適切な画面へ遷移。
/api/signin/emailはbodyからemailを受け取り以下を実行する
するとメールアドレスへマジックリンクのメールが届く。
この時にcookieにemailの情報などを書き込んでおく(ドキュメントではlocalstorageに書き込んでいる)
マジックリンクを開いたら /api/signin/email/callback?apiKey=xxx にリダイレクトしておくようにする。
/api/signin/email/callbackでは以下の2つを実行する。まずはこのpathが合ってるかどうかの確認と、verifyである。
ここまで行えたらtokenを得てhttpOnlyでsetCookieしながら適切なページへリダイレクトする。この時のcookieは1weekぐらいにしておく。理由はfirebaseのtokenは1hでexpireするからである。
このまででログイン処理が行えた。
次tokenを必要とするAPIへのclientの実装を考える。基本的にの必要なAPIはhttpOnlyにしてる以上ブラウザから直接流れないのでNode.jsでproxyする必要がある。
そのため/meのようなAPIには /api/me へ一旦リクエストを送り、/meへ送る時にcookieからtokenを付与する。またcookieが存在しているが403を返す場合、expireされているのでfirebase.auth().currentUser.refreshTokenを用いてtokenをrefreshする。
このための/api/refreshとかを使っておいても良いかも。この時にcookieに値を書き込む。
注意点としてはこの後まだこのrefreshTokenが使えるかどうかである。1度使用したrefreshTokenを再度利用できない場合、firebase sdk側へどうにかrefreshしたことを教えておかないと、次のrefreshで詰む。
もしかしたらこのproxyしてるAPIのときはcookieをsetするのと同時にsetしたtimestampもsetCookieしてるほうが良いかもしれない。そうすればtimestampから1時間以上経っている時にAPIリクエストしようとした場合、その前にrefreshしてから実行するみたいなことが行えるはず。
そうするとtokenとしてsetCookieしたcookieがexpireされない限りユーザーはrefreshし続けることができる。tokenのsetCookieは1weekが良いとこな気がする。(ITPもあるので)
logoutは以下を叩いてあげてcookieを過去時間設定して消すみたいなことをすればよさそう。
これ結果やっぱりrefreshの機構を作る時の実装の複雑さなどが勝つので却下。
そのかわりにSWでの管理をすることにした。