🔐

NextAuthを試す

2023/01/14に公開

NextAuth

Authentication for Next.js

各Version

"next": "13.0.6",
"next-auth": "^4.18.6",

パッケージインストール

yarn add next-auth

簡単なサンプル実装

今回はGoogle認証を試して見たいと思います。

Google側のキー取得や設定

OAuth 同意画面の設定

  1. Google API Console から「OAuth 同意画面」を選択
  2. 今回はテスト用なので外部を選択し作成
    image1
  3. アプリの情報を設定します
    image2
  4. スコープの設定はそのままで次に進みます

参考URL

クライアントIDとクライアントシークレットを取得

  1. Google API Console から「認証情報」を選択
  2. 「認証情報を作成」>「OAuth クライアント ID」を選択
    image3
  3. アプリケーションの種類は「ウェブアプリケーション」を選択
  4. 名前を適当な名前に設定
  5. リダイレクトURIは http://localhost:3000/api/auth/callback/google を設定
    image4

作成するとクライアントIDとクライアントシークレットが表示されるので保存しておきます。
image5

API route を追加

pages/api/auth/[...nextauth].ts を以下内容で作成します。

import NextAuth from 'next-auth';
import GoogleProvider from 'next-auth/providers/google';

export default NextAuth({
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID ?? '',
      clientSecret: process.env.GOOGLE_CLIENT_SECRET ?? '',
    }),
  ],
  session: { strategy: 'jwt' },
});

各Providerに関してはこちら参照
GoogleのOAuth2.0に関連するドキュメントはこちら

callbacksに関して

Callbacks | NextAuth.js

呼ばれる順番

  1. signIn
  2. jwt
  3. redirect
  4. session

signIn後に特定のページに遷移させる方法

  • signIn() の第二引数の callbackUrl に特定のページを設定
  • ただし redirect を設定しているとそちらが優先されるので、必要ない場合は削除しとく

sessionに関して

  • strategy
    • デフォルトは jwt

_app.tsxにSessionProvider追加

import { SessionProvider } from 'next-auth/react';
import type { AppProps } from 'next/app';

function MyApp({ Component, pageProps: { session, ...pageProps } }: AppProps) {
  return (
    <SessionProvider session={session}>
      <Component {...pageProps} />
    </SessionProvider>
  );
}

export default MyApp;

SignIn, SignOutを試す画面を作成

import { signIn, signOut, useSession } from 'next-auth/react';

export default function Page() {
  const { data: session } = useSession();
  return session ? (
    <>
      Signed in <br />
      <button onClick={() => signOut()}>Sign Out</button>
    </>
  ) : (
    <>
      Not signed in <br />
      <button onClick={() => signIn()}>Sign In</button>
    </>
  );
}

middlewareでページに認証をかける

https://next-auth.js.org/configuration/nextjs#middleware
事前に NEXTAUTH_SECRET を設定する必要があります。以下コマンドで生成したランダムな値を .env.local に設定しときます。

openssl rand -base64 32
.env.local
NEXTAUTH_SECRET=生成したランダムな値

次に middleware.ts を以下内容でプロジェクトのルートディレクトリ、または pages と同階層に作成します。

export { default } from 'next-auth/middleware';

↑だけで、全ページにSignInしているかのチェックがかかります。
特定のページのみチェックしたい場合は

export { default } from 'next-auth/middleware';

export const config = {
  matcher: ['/xxx'],
};

特定のページを指定した config を返す事で実現できます。

バックエンド側での認証チェック

バックエンド サーバーで認証する  |  Authentication  |  Google Developers
↑こちらを参考に実装してみます。バックエンド側はNode.jsサーバーの想定です。

googleapis/google-auth-library-nodejs: 🔑 Google Auth Library for Node.js
↑こちらのパッケージを使えばverify部分はサクッと実装できます。

import { OAuth2Client } from 'google-auth-library';

const client = new OAuth2Client();

const verify = async (
  idToken: string,
  sub: string
): Promise<boolean> => {
  const ticket = await client.verifyIdToken({
    idToken,
  });
  const payload = ticket.getPayload();
  return payload?.sub === sub;
};

参考URL

Discussion