NextAuth.jsのセッション取得はどこからのリクエストかに注意

📕 新コースを公開しました。→クーポン掲載ページ

NextAuth.jsはNext.jsのアプリケーションに認証機能を簡単につけられるオープンソースのパッケージです。

https://next-auth.js.org/

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 を使っていました。

参考:

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についても少し詳しくなれてよかったです。

🎓✍️コース一覧

プログラミング関係のビデオコースを提供しています。クーポンも発行していますので、ぜひ一度チェックしてみてください。

Twitter @takumafujimoto

記事を読んでいただきありがとうございます。ツイッターではプログラミング以外についてや、たまにクーポン情報もツイートしたり。。。ツイッターでもお待ちしてます。