🚦
next-authとgetServerSide(Static)Props使うときの__NEXT_DATA__に注意
next-authなどでクライアントログインを仕掛けていてgetServerSidePropsやgetStaticPropsでちゃんと認証かけてないとだだ漏れするので気をつけましょうねという話。
通常のサーバーサイド開発に慣れていればあまりハマるようなことではないのだが、知らないで使うと危ないので記述しておく
例示
例えば下記のようなコードで考えてみる。
だいたいログイン判定はクライアントなら_app.js
にて書くだろう。
// _app.jsx
import { signIn, useSession } from "next-auth/client"
export const NeedLogin = ({children}) => {
const [session, loading] = useSession()
if (loading) {
return null
}
if (!session ) {
return <div>
Not signed in <br />
<button onClick={signIn}>Sign in</button>
</div>
}
return children
}
function MyApp({ Component, pageProps }) {
return (
<Provider options={{ clientMaxAge: 60 }} session={pageProps.session}>
<NeedLogin>
<Component {...pageProps} />
</NeedLogin>
</Provider>
)
}
export default MyApp
そしてページ側はこのような具合に書いてみる
// pages/somePage.jsx
import React from "react"
import { useSession } from "next-auth/client"
import { getSomeSecretData } from "../lib/getSomeData"
export default function Page({data}) {
const [, loading] = useSession()
if (loading) {
return null
}
return (
<div>
Home
<pre>Need Login: {JSON.stringify(data)}</pre>
</div>
)
}
export async function getServerSideProps() {
const data = getSomeSecretData() // 例えばこれがログイン後にのみ表示させたいデータだとする
return {
props: { data },
}
}
そうするとログイン後、ログイン前でこんな感じで表示されるはずだ
ログイン前 | ログイン後 |
---|---|
これにてめでたしめでたし。ではない。
ログイン前のページでinspectorをしてみよう
<script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{"data":["This","Data","Need","Login"]},"__N_SSP":true},"page":"/","query":{},"buildId":"development","isFallback":false,"gssp":true}</script>
このように__NEXT_DATA__
としてgetServerSidePropsの値は表示されてしまう
対応方法
getServerSideProps
で行う場合はgetSession
でチェックを入れましょう。
import { useSession,getSession } from "next-auth/client"
export async function getServerSideProps(context) {
const session = await getSession(context) // awaitを忘れずに
if (!session) {
return { props: {} }
}
const data = getSomeSecretData()
return {
props: { data },
}
}
こうすれば__NEXT_DATA__
にも表示されません。 [1]
[1]: await
を忘れるとsession
がPromiseになってしまいif(!session)
を通過してしまうので注意
<script id="__NEXT_DATA__" type="application/json">{"props":{"pageProps":{},"__N_SSP":true},"page":"/","query":{},"buildId":"development","isFallback":false,"gssp":true}</script>
また、getStatciProps
の場合はリクエストなどのcontext
が取得できないためこのままではできません。もともとgetStatciProps
はログインが必要などのユースケースは含まれてないため、どうしてもgetStaticProps
を利用する必要がある場合はAPI経由などで取得をするのが良いでしょう。
APIの場合であれば上記同様getSession
が利用できます
Discussion