NextAuth.jsはNext.jsのアプリケーションに認証機能を簡単につけられるオープンソースのパッケージです。
Next.jsのプロジェクトでテストコードを書いていて、セッション判定のところでハマったので、書き残しておきます。
問題の箇所
PlayWrightのテストコードを書いていて、Next.jsアプリケーションのAPIルートへfetchするコードを書きました。
そのfetch先のコード内では認証済みユーザーかどうかを判定するコードを書いていました。
テスト実行時のブラウザでもログインを行っていたので、認証できているはずなのです。でも何度やってもそのAPIを叩くところで認証がなくてうまくいかなかったのです。
セッション判定について
NextAuth.jsでは現在認証済みかどうかをsessionを取得することで判定できます。
ただし、注意が必要なのはクライアントサイドとサーバーサイドでやり方が異なる点です(NextAuth.jsに限らずNext.jsアプリケーションでは大抵異なるとは思いますが)。
const { data: session } = useSession()
const session = await getSession()
今回のケースではAPIとして書いていたので、サーバーサイド用の getSession
を使っていました。
参考:
- https://next-auth.js.org/getting-started/client
- https://qiita.com/kage1020/items/e5b0053d7046a9b1f628
getSessionは非推奨?
うまくセッションが取得できなかったので、調べてみました。そうするとgetSessionは現在は非推奨というのを見つけました。
代わりに unstable_getServerSession
を使うようです。
ただし接頭辞に unstable
がついているように、これは将来のバージョンで変更になる可能性があります。
const session = await unstable_getServerSession(context.req, context.res, authOptions)
ただ、unstableなので、まだgetSessionでもいいとは思います。
この unstable_getServerSession
でやってみましたが、これでもうまくいきませんでした。
さらにテストではなく、通常の開発サーバを立ち上げて色々触っている中では、getSessionはうまく機能していることが確認できました。
なので今回に関しては getSession に問題があるわけではなかったです。
requestの凡ミス
結局原因はなんだったかというと、getSessionへ渡す引数 req
に問題があったわけです。
const session = await getSession({ req });
よくよく考えれば当たり前ですが、現在のセッションを取得するためにreqを見ています。つまり、HTTPリクエストがどこから飛んでくるかが重要になります。
Next.jsのアプリケーション内の、クライアントサイドコードでfetchを書いていれば、(その時のページで認証済みであれば)認証済みの状態でリクエストすることになります。これならうまくいきます。
今回の場合は、テストコードで直接APIを叩いていたため、reqが認証済みのものではなかったということです。その結果、そもそもそのリクエストオブジェクトにはセッションがないのでないものは取れないからうまくいかなかったのです
以上、考えれば当たり前な凡ミスでした。
調べる中で、NextAuth.jsについても少し詳しくなれてよかったです。