NextAuth v5とFirebase Authenticationで、Next.jsのバックエンドをBFFとして利用して既存APIサーバーと連携する
fetchに使う:
import { auth } from '@/app/api/auth/[...nextauth]/route'
const res = await fetch('http://localhost:8000/customers', { method: 'GET', headers: { Authorization: `Bearer ${(await auth())?.user?.token}` } })
サーバーセッションにfirebaseのアクセストークンを突っ込みたい。firebaseが払い出すアクセストークンは30分ごとに有効期限が切れてしまう & サーバーサイドで外部APIを叩きたい、という2つのモチベーションを満たすため。
getIdToken()はさすがにサーバーサイドでは動かないだろう...。ローカルストレージ使ってるし。
じゃあonIdTokenChangedコールバックを利用して更新するか。
useEffectに何も依存配列を入れないと、初回のsessionがundefinedな状態でuseEffectが走る。
一方でsession.statusなどを依存配列に入れると、useEffectが無限に走ってしまう。
かつ、どちらにせよsessioinのデータ更新は行われていないようだ。
useEffect(() => auth.onIdTokenChanged(async (user) => {
const idToken = await user?.getIdToken()
if (idToken && session.data?.user?.token !== idToken) {
console.log('onIdTokenChanged: updating session id token!') // 無限にログが出る
await session.update({ ...session.data, user: { ...session.data?.user, token: idToken } })
console.log('updated:', session.data)
}
}), [session.status])
sessioinの振る舞いについてもう少し学ぼう。
sessionの型情報によると、userというプロパティを持っているらしいが、useSessionの結果取得できる値には data、statusというプロパティが生えている。
クライアントサイドでのセッション取得の項目を調べると SessionProvider
と useSession
で実現できる。ただしこの例は、Page Routerを使ったものだ。App Router & NextAuth v5だとどうなるかな...。
App Router と Next Auth v5でセッション更新する記事があった。
これはfirebase authとは関係ないけど、クライアントサイドで更新したセッションをサーバーサイドで更新する流れがよく分かった。
useSession()
で取得した update
関数を利用すると、 POST /api/auth/session
を叩くことになる。単にクライアントサイドで更新をかけるだけでなく、サーバーサイドでも更新処理を書く必要があるっぽい。
useActionStateも使いたいが、react canaryを利用する必要があるらしく、今は置く...。