Wiz テックブログ

Wizは、最新のIoTやICTサービスをお客様に届ける「ITの総合商社」です。

NextAuth.jsでカスタムログインページを実装する方法

f:id:mt_816:20210804192049p:plain

こんにちは、フロントエンドエンジニアの松尾です。

最近はNext.jsが盛り上がっており、エコシステムも充実してきています。

その中に、NextAuth.jsという認証機能を簡単に実装できるライブラリがあり非常に便利です。

next-auth.js.org

本記事では、NextAuth.jsを使用したカスタムログインページの実装方法について説明したいと思います。

NextAuth.jsとは?

NextAuth.jsとは、Next.jsに簡単に認証機能を実装できるライブラリです。

アカウント登録も必要なく、ライブラリをインストールするだけで実装できます。

また、メールアドレス認証に加えて、GoogleTwitterFacebookといったサービスのOAuth認証を組み込むことが可能です。

NextAuth.jsでログインする場合、以下のようにNextAuth.js専用のログインページに遷移する形となっており、自由にページをカスタマイズできません。

f:id:mt_816:20210803152037p:plain

認証機能を特定のページに組み込みたい場合も多いのではないでしょうか?

そこで、カスタムログインページの実装方法について説明したいと思います。

実装方法

まず初めに、next-authをインストールしてください。

npm install next-auth

次に、NextAuth.jsのAPIルートを作成します。

/pages/api/auth/[...nextauth].jsを作成し、以下を記述してください。

import NextAuth from 'next-auth'
import Providers from 'next-auth/providers'

// NextAuth.js関数に渡すオプション
const options = {
  providers: [
    Providers.Credentials({
      // NextAuthの認証関数。credentialsにログイン情報が格納される。
      authorize: async credentials => {
        if (
          // ログインID・パスワードは環境変数にて設定する。
          credentials.login === process.env.NEXT_PUBLIC_LOGIN_ID &&
          credentials.password === process.env.NEXT_PUBLIC_PASSWORD
        ) {
          // ログイン成功後ユーザー情報を返却する。値はsessionに格納される。
          return Promise.resolve({ name: 'admin' })
        } else {
          // ログイン失敗後認証を拒否し、エラーメッセージを返却する。
          return Promise.resolve(null)
        }
      },
    }),
  ],
  // ログインページを指定する。今回はトップページのため'/'を指定。
  pages: {
    signIn: '/',
  },
}

export default (req, res) => NextAuth(req, res, options)

最後に、認証機能を実装するページに以下を記述します。

import { useRouter } from 'next/router'
import { getCsrfToken, useSession, signOut } from 'next-auth/client'

const LoginPage = ({ csrfToken }) => {
  const { error } = useRouter().query
  const [ session ] = useSession()

  return (
    <div>
      <h1>カスタムログインページ</h1>
      {session ? (
        // ログイン状態の場合。ユーザー名、ログアウトボタンを表示。
        <>
          <div>ユーザー:{session.user?.name}</div>
          <button onClick={signOut}>ログアウト</button>
        </>
      ) : (
        // ログアウト状態の場合。入力フォームを表示。
        <form method='post' action='/api/auth/callback/credentials'>
          <input name='csrfToken' type='hidden' defaultValue={csrfToken} />
          <label>
            <div>ログインID</div>
            <input name='login' />
          </label>
          <label>
            <div>パスワード</div>
            <input name='password' type='password' />
          </label>
          <div>
            <button type='submit'>ログイン</button>
          </div>
          {/* ログイン失敗後、エラーメッセージを表示。*/}
          {error && <div>ログインID又はパスワードが間違っています。</div>}
        </form>
      )}
    </div>
  )
}

// POSTリクエスト(サインイン・サインアウトなど)に必要なCSRFトークンを返却する。
export const getServerSideProps = async context => {
  return {
    props: {
      csrfToken: await getCsrfToken(context),
    },
  }
}

export default LoginPage

ログインに成功すると、useSession関数のsessionにユーザー情報が格納されます。

以下のように、sessionにユーザー情報が含まれているか否かで表示を切り替えています。

▼ ログイン前

f:id:mt_816:20210804110407p:plain

▼ ログイン後

f:id:mt_816:20210804110414p:plain

また、認証失敗時に関しては、URLパラメータのerrorを参照し、エラーメッセージを表示させています。

▼ ログイン失敗時

f:id:mt_816:20210804135835p:plain

まとめ

以上NextAuth.jsを使用したカスタムログインページ実装についての説明でした。

今回は簡易的な認証機能の例でしたが、NextAuth.jsは、GoogleTwitterFacebookといったサービスの認証機能の組み込みや、データベース・メール送信サービスとの連携も可能となっています。

NextAuth.jsは無料で使用できますので、興味ある方は是非お試しください!

最後になりますが、Wizではエンジニアを募集中です。

興味のある方は是非覗いてみてください↓

careers.012grp.co.jp