[Next.js] authjs(NextAuth)를 활용한 인증 기능 구현하기(3) : Credentials Provider 설정하기

문지은·2024년 1월 25일
1

Next.js - App Router

목록 보기
14/20
post-thumbnail

authjs를 사용하여 소셜 로그인이 아닌 현재 구축하고 있는 앱만의 로그인 시스템을 구축해보자.

Credentials Provider

  • 이를 설정하기 위해서는 Credentials 속성을 Provider 배열의 요소로 추가해야 한다.
    • 이렇게 추가한 Credentials 객체는 로그인 페이지 양식을 생성하는데 사용된다.
    • 로그인 페이지에 이메일과 비밀번호 필드를 가지도록 설정해보자.
      • 상황에 따라 사용자 이름 필드를 추가할 수 있다.
    • 각 필드에 대한 라벨과 타입, 그리고 플레이스 홀더를 지정할 수도 있다.
      • 이렇게 지정된 속성들은 input 태그를 렌더링할 때 사용된다.
    • 정의한 credentials 를 기반으로 로그인 혹은 회원가입을 했을 때 입력한 값은 authorized 함수로 전달된다.
      • 이 함수는 사용자가 입력한 필드 값을 추출해 내부적으로 데이터 타입부터 가입 여부, 인증 여부 등을 확인하고 데이터베이스에 생성한 데이터를 반영하는 역할을 한다.

  • 우선, 위 로직을 구현하는 데 유용하게 사용할 수 있는 bcrypt 모듈을 다운로드 한다.
    • 이 모듈은 사용자가 입력한 비밀번호를 평문이 아닌 암호화된 형태로 데이터베이스에 저장하고, 동시에 사용자가 요청으로 전달한 비밀번호를 암호화된 비밀번호와 비교하는 데 사용할 수 있다.
npm install bcrypt
npm install -D @types/bcrypt
  • 기존의 사용자 모델에 hashedPassword 라는 필드를 추가해야 한다.

prisma/schema.prisma

model User {
  id            String    @id @default(cuid())
  name          String?
  email         String?   @unique
  emailVerified DateTime?
  image         String?
  hashedPassword String?
  accounts      Account[]
  sessions      Session[]
}
  • 마이그레이션 진행
npx prisma migrate dev
  • Credentials 객체 추가

app/api/auth/[…nextauth]/route.ts

...
import CredentialsProvider from "next-auth/providers/credentials";
import bcrypt from "bcrypt";

export const authOptions = {
  ...
  providers: [
    CredentialsProvider({
      name: "Credentials",
      credentials: {
        email: { label: "Email", type: "email", placeholder: "Email" },
        password: {
          label: "Password",
          type: "password",
          placeholder: "password",
        },
      },
      async authorize(credentials, req) {
        // credentials 인자 값을 통해 사용자가 입력한 이메일, 패스워드 추출
        if (!credentials?.email || !credentials?.password) return null;

        // 사용자 존재 여부 확인
        const user = await prisma.user.findUnique({
          where: { email: credentials.email },
        });

        // 사용자가 없으면 null 리턴
        if (!user) return null;

        // 데이터베이스의 암호화된 비밀번호와 사용자가 입력한 비밀번호가 같은지 비교
        const passwordMatch = await bcrypt.compare(
          credentials.password,
          user.hashedPassword!
        );

        // 비밀번호가 일치하면 사용자 리턴
        return passwordMatch ? user : null;
      },
    }),
 ...
};

const handler = NextAuth(authOptions);

export { handler as GET, handler as POST };
  • 브라우저에서 확인

  • 현재는 사용자가 없기 때문에 오류가 발생함.

  • 다음 게시글에서 회원가입 로직을 구현해보겠다!
profile
코드로 꿈을 펼치는 개발자의 이야기, 노력과 열정이 가득한 곳 🌈

0개의 댓글