🚀

【Next.js和訳】Authentication

6 min read

この記事について

株式会社 UnReact はプロジェクトの一環としてNext.js ドキュメントの和訳を行っています。

この記事は、Authenticationの記事を和訳したものです。

記事内で使用する画像は、公式ドキュメント内の画像を引用して使用させていただいております。

Authentication

認証はユーザーが誰であるかを確認し、承認はユーザーがアクセスできる範囲を制御します。Next.js は複数の認証パターンをサポートしており、それぞれ異なるユースケースに対応しています。このページでは、それぞれのケースについて説明し、制約条件に応じて選択できるようにします。

認証パターン

どのような認証パターンが必要かを判断するための最初のステップは、必要なデータ取得方法を理解することです。次に、どの認証プロバイダが戦略をサポートしているかを判断します。主に 2 つのパターンがあります。

  • 静的生成を使用してサーバでロード状態をレンダリングし、その後、クライアント側でユーザデータを取得する。
  • 認証されていないコンテンツのフラッシュをなくすために、サーバーサイドでユーザーデータを取得する。

静的に生成されたページの認証

Next.js は、ブロックデータの要求がない場合、ページが静的であると自動的に判断します。つまり、ページ内にgetServerSidePropsgetInitialPropsが存在しないことを意味します。代わりに、ページはサーバーからのローディング状態をレンダリングし、続いてクライアントサイドでユーザーをフェッチすることができます。

このパターンの利点の一つは、ページをグローバル CDN から提供し、next/linkを使ってプリロードできることです。実際には、これにより、TTI(Time to Interactive)が速くなります。

例えば、プロフィールページの例を見てみましょう。これは、最初にローディングスケルトンをレンダリングします。ユーザーへのリクエストが終了すると、ユーザーの名前が表示されます。

pages/profile.js
import useUser from '../lib/useUser'
import Layout from '../components/Layout'

const Profile = () => {
  // クライアントサイドでユーザーを取得する
  const { user } = useUser({ redirectTo: '/login' })

  // サーバー・レンダーのローディング状態
  if (!user || user.isLoggedIn === false) {
    return <Layout>Loading...</Layout>
  }

  // ユーザーリクエストが終了したら、ユーザーを表示する
  return (
    <Layout>
      <h1>Your Profile</h1>
      <pre>{JSON.stringify(user, null, 2)}</pre>
    </Layout>
  )
}

export default Profile

このを実際に見ることができます。with-iron-sessionの例で、その動作を確認してください。

サーバーにレンダリングされたページの認証

ページからgetServerSidePropsというasync関数をエクスポートすると、Next.js はリクエストごとにgetServerSidePropsから返されたデータを使ってこのページを事前にレンダリングします。

export async function getServerSideProps(context) {
  return {
    props: {}, // プロップとしてページコンポーネントに渡されます。
  }
}

プロファイルの例をサーバーサイドレンダリングを使うように変換してみましょう。セッションがある場合は、ページの Profile コンポーネントに user をプロップとして返します。この例では、ローディング スケルトンがないことに注意してください。

pages/profile.js
import withSession from '../lib/session'
import Layout from '../components/Layout'

export const getServerSideProps = withSession(async function ({ req, res }) {
  // リクエストに基づいて、ユーザーのセッションを取得します
  const user = req.session.get('user')

  if (!user) {
    return {
      redirect: {
        destination: '/login',
        permanent: false,
      },
    }
  }

  return {
    props: { user },
  }
})

const Profile = ({ user }) => {
  // ユーザーを表示します。読み込み状態は必要ありません
  return (
    <Layout>
      <h1>Your Profile</h1>
      <pre>{JSON.stringify(user, null, 2)}</pre>
    </Layout>
  )
}

export default Profile

このパターンの利点は、リダイレクトする前に認証されていないコンテンツのフラッシュを防ぐことです。注意すべき点は、getServerSidePropsでユーザーデータを取得すると、認証プロバイダへのリクエストが解決するまでレンダリングがブロックされることです。ボトルネックになって TTFB(Time to First Byte)が増えるのを防ぐために、認証ルックアップが高速であることを確認する必要があります。そうでなければ、静的生成を検討してください。

認証プロバイダ

ここまでは認証のパターンについて説明してきましたが、ここからは具体的なプロバイダについて説明し、Next.js でどのように使われているかを見ていきましょう。

独自のデータベース

ユーザーデータの入った既存のデータベースがある場合は、プロバイダに依存しないオープンソースのソリューションを利用するのがよいでしょう。

  • 低レベルで暗号化されたステートレスなセッションユーティリティが必要な場合は、next-iron-sessionを使用します。
  • 一方、ビルトインプロバイダ(Google、Facebook、GitHub など)、JWT、JWE、メール/パスワード、マジックリンクなどを備えたフル機能の認証システムが必要な場合は、next-authを使用します。

これらのライブラリは、どちらの認証パターンにも対応しています。Passportに興味がある方は、安全で暗号化されたクッキーを使った例もあります。

他の認証機関

他の認証プロバイダの例を見るには、examples フォルダをチェックしてください。

関連項目

次に行うべきことの詳細については、以下のセクションをお勧めします。

https://nextjs.org/docs/basic-features/pages
https://nextjs.org/docs/basic-features/data-fetching

Discussion

ログインするとコメントできます