概要
AIでの開発が盛んな昨今ではあるが、一旦ちゃんと理解したいのでAuth.jsを使ってNext.jsのフレームワークで認証機能を人力実装してみる。
前回がインストール + 設定ファイルの用意だったので今回からメインの設定に入っていく。
前提
まずは基本となるメールアドレスとパスワードを使った認証を実装してみる。
下記のページの内容を実施してみる。
方法
-
auth.tsを下記のように修正(credentialsのプロバイダーのimportと認証プロバイダーへの追加、これをすることでメアド + パスワードという古からのロングセラーな方法で認証が可能になる。)
auth.ts// TODO: 本モジュールはsrc/lib/直下に移動予定 import NextAuth from "next-auth" import { ZodError } from "zod" import Credentials from "next-auth/providers/credentials" import { signInSchema } from "./lib/zod" // Your own logic for dealing with plaintext password strings; be careful! import { saltAndHashPassword } from "@/utils/password" import { getUserFromDb } from "@/utils/db" export const { handlers, auth } = NextAuth({ providers: [ Credentials({ // You can specify which fields should be submitted, by adding keys to the `credentials` object. // e.g. domain, username, password, 2FA token, etc. credentials: { email: {}, password: {}, }, authorize: async (credentials) => { try { let user = null const { email, password } = await signInSchema.parseAsync(credentials) // logic to salt and hash password const pwHash = saltAndHashPassword(password) // logic to verify if the user exists user = await getUserFromDb(email, pwHash) if (!user) { throw new Error("Invalid credentials.") } // return JSON object with the user data return user } catch (error) { if (error instanceof ZodError) { // Return `null` to indicate that the credentials are invalid return null } } }, }), ], }) -
src/components/auth/直下にsign-in.tsxを定義して下記の内容を記載(サインイン用のフォームをコンポーネントとして追加)src/components/auth/sign-in.tsximport { signIn } from "../../../auth" export function SignIn() { return ( <form action={async (formData) => { "use server" await signIn("credentials", formData) }} > <label> Email <input name="email" type="email" /> </label> <label> Password <input name="password" type="password" /> </label> <button>Sign In</button> </form> ) } -
下記を実行してZodというスキーマライブラリを導入(バリデーションと型定義を一緒に面倒見てくれるもの)
pnpm add zod -
プロジェクトルートにlibディレクトリを作成しその中にzod.tsを追加し下記のように記載(型定義とバリデーションルールの設定を実施)
lib/zod.tsimport { object, string } from "zod" export const signInSchema = object({ email: string({ required_error: "Email is required" }) .min(1, "Email is required") .email("Invalid email"), password: string({ required_error: "Password is required" }) .min(1, "Password is required") .min(8, "Password must be more than 8 characters") .max(32, "Password must be less than 32 characters"), })