Next.jsにAuth0による認証機能を追加

Next.jsによるWebアプリケーションにAuth0による認証機能を追加する方法の簡単なメモです。

以前、ViteAuth0を少し試しましたが、Next.jsではやり方が異なるみたいです。以下のその①に相当しますが、プロフィール画像までは出しません。今回はほぼ初めて使う不慣れなTypeScriptでやっています。

準備

  • Auth0のアカウントを作成する
  • Auth0のテナントを作成及び/又はそのテナントに切り替える

Auth0のアプリケーションを作成する

  1. Auth0のダッシュボードで、アプリケーションを作成する。
    1. Auth0のダッシュボードのApplicationsから[+ Create Application]をクリックする。
    2. アプリケーション名を入力する。例:”My Next.js Autheticated App”
    3. アプリケーションタイプとして、”Regular Web Applications”を選択し、[Create]ボタンをクリックする。
  2. アプリケーションを設定する。
    1. Settingsタブで以下の設定をしますが、最初から表示されている設定は、.envファイルで設定します。
    2. Allowed Callback URLsに、”http://localhost:3000/api/auth/callback”を設定する。
    3. Allowed Logout URLsに、”http://localhost:3000/”を設定する。
    4. 一番下までスクロールし、[Save Changes]ボタンをクリックする。

.envファイルを設定する

.env.sample に以下を追加する。


:
AUTH0_SECRET=
AUTH0_BASE_URL=
AUTH0_ISSUER_BASE_URL=
AUTH0_CLIENT_ID=
COOKIE_SECRET=

.ignore.env.sample 以外の .env*ファイルが無視されるよう指定されていることを確認します。

例えば、.env.local ファイルに次のように設定します。詳細はこちらを参照。

:
AUTH0_SECRET= // Auth0のApplicationsのsettingのClient ID
AUTH0_BASE_URL= // http://localhost:3000 等
AUTH0_ISSUER_BASE_URL= // Auth0のApplicationsのsettingのDomain 例:https://pitang1965.jp.auth0.com
AUTH0_CLIENT_ID= // Auth0のApplicationsのsettingのClient Secret
AUTH0_SECRET= // 32文字以上のランダムな値

上記の AUTH0_SECRETの値は、ターミナルで以下のコマンドで生成することができます。

$ node -e "console.log(crypto.randomBytes(32).toString('hex'))"

@auth0/nextjs-auth0をインストールする

$ yarn add @auth0/nextjs-auth0

Next.jsアプリケーションにAPIを追加する

  1. src\pages\apiフォルダにauthフォルダを作成し、[…auth0].jsファイルを作成する。
import { handleAuth } from '@auth0/nextjs-auth0';

export default handleAuth();

2. src\pages_app.tsx に以下の行を追加する。

:

import { UserProvider } from '@auth0/nextjs-auth0'; <--- この行



:

function MyApp({ Component, pageProps }: AppPropsWithLayout) {
:

  const getLayout = Component.getLayout ?? ((page) => page);
  return getLayout(
    <UserProvider> <--- この行
      <Component {...pageProps} />
    </UserProvider> <--- この行
  );
}

3. src\components\Navbar.tsx を次のように設定しました。

  • [ログイン]ボタンを押すと、Auth0の認証のダイアログが表示されます。
  • 認証されるとホームページに戻り、[ログイン]ボタンが消えて、[ログアウト]ボタンと、「こんにちは、○○○さん。」が表示されます。
  • [ログアウト]ボタンをクリックすると、[ログアウト]ボタンが消えて、「ログアウト中です。お待ちください…」が一瞬表示され、やがて[ログイン]ボタンが表示されます。
import React, { useState, useEffect } from 'react';
import TopMenu from '../components/TopMenu';
import Link from 'next/link';
import { useUser } from '@auth0/nextjs-auth0';

export default function Navbar() {
  const { user, error, isLoading } = useUser();
  const [message, setMessage] = useState('');

  // ログアウトボタンを押してログアウトするまでの間
  const [isLoggingOut, setIsLoggingOut] = useState(false);

  useEffect(() => {
    if (error) {
      setMessage(`エラー:${error}`);
      setIsLoggingOut(false);
    } else if (isLoading) {
      setIsLoggingOut(true);
      setMessage(`読み込み中...`);
    } else if (user) {
      setMessage(`こんにちは、${user.name}さん。`);
      setIsLoggingOut(false);
    } else {
      setMessage(`未ログイン`);
      setIsLoggingOut(false);
    }
  }, [user, error, isLoading]);

  return (
    <>
      <nav className='flex justify-between items-center'>
        <div className='basis-1/3'>
          <TopMenu />
        </div>
        <div className='basis-1/3 text-center'>
          <Link href='/' passHref>
            <p className='text-2xl font-bold text-grey-800'>バス時刻表</p>
          </Link>
        </div>
        <div className='basis-1/3 text-right'>
          <Link href='/api/auth/logout'>
            <a
              onClick={() => {
                setIsLoggingOut(true);
                setMessage('ログアウト中です。お待ちください...');
              }}
              className={`rounded bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 ${
                !user || isLoggingOut ? 'hidden' : ''
              }`}
            >
              ログアウト
            </a>
          </Link>
          <Link href='/api/auth/login'>
            <a
              className={`rounded bg-blue-600 hover:bg-blue-700 text-white py-2 px-4 ${
                user || isLoggingOut ? 'hidden' : ''
              }`}
            >
              ログイン
            </a>
          </Link>
        </div>
      </nav>
      {user && <p className='mx-2 self-center mt-2'>{message}</p>}
    </>
  );
}

これで、next devスクリプトを再起動して、http://localhost:3000/apu/auth/login にアクセスすると、次の画面が表示されるはずです。

Auth0のログイン画面

Auth0のApplication URIを設定する

Auth0のダッシュボードで当該ApplicationApplication URIsセクションで下記の設定に変更します(デプロイ先を追加)。

Allowed Callback URLs

http://localhost:3000/api/auth/callback,https://j-bus-time-table.vercel.app/api/auth/callback

Allowed Logout URLs

http://localhost:3000, https://j-bus-time-table.vercel.app

Vercelにデプロイする

GitHubのリポジトリを選択してデプロイします(詳細省略)が、以下の環境変数を設定します。

AUTH0_SECRET:******
AUTH0_BASE_URL:https://j-bus-time-table.vercel.app
AUTH0_ISSUER_BASE_URL:https://pitang1965.jp.auth0.com
AUTH0_CLIENT_ID: ******
AUTH0_CLIENT_SECRET: ******