소셜 로그인, next-auth

이가리·2023년 3월 16일
0

NextJS 에서 next-auth 라는 라이브러리를 이용하면 google, kakao 소셜 로그인 기능을 쉽게 관리 할 수 있다고 해서 도전! 처음 구현하다 보니 잘 할 수 있을까 싶었는데 next-auth 최고!

next-auth

설치

yarn을 쓰고 있기 때문에 yarn add를 통해 설치했다.

yarn add next-auth

API 루트 추가

pages/api/auth 폴더 안에 [...nextauth].js 파일을 생성해 준다.

[...nextauth].js 파일에 원하는 소셜 로그인 provider를 providers 객체에 추가해준다. google 소셜 로그인을 위해 GoogleProvider를 providers 배열 안에 넣어준다.

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,
    }),
    // 여기에 다른 provider를 추가하면 된다.
  ],
});

.env 환경 변수에 client Id와 client Secret 값을 추가해 provider에 해당 값을 process.env.CLIENT_ID로 불러와준다.
.env 파일은 gitignore에 넣어 github에 올라가지 않게 관리!

SessionProvider

next-auth/react 에서 제공하는 SessionProvider로 Component를 감싸 nextjs에서 useSession 훅을 통해 session 정보를 접근 할 수 있도록 한다.

// app.js

import { SessionProvider } from "next-auth/react";

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

export default app;

이렇게 컴포넌트를 감싸줌으로써 session 정보에 접근할 수 있다.


signIn, useSession

이제 next-auth의 signIn, signOut, useSession을 쓸 수 있다.
signIn 함수로 로그인을 간단하게 구현할 수 있다. 최고최고

import { signIn } from "next-auth/react";

const socialLogin = (e, provider) => {
	e.preventDefault();
	signIn(provider); 
}

두 개 이상의 소셜 로그인 구현 시엔 파라미터로 provider를 넣어주면 된다.

// google
<button type="button" onClick={e => socialLogin(e, "google")}>Google</button>

// kakao
<button type="button" onClick={e => socialLogin(e, "kakao")}></button>

이제 로그인 완성..이다! 이제 session access token을 서버에 보내 로컬 access 토큰과 refresh 토큰을 받아와야했다.

session 토큰을 위해 [...nextauth].js 파일에서 callbacks 객체를 추가해 session으로 해당 계정의 access token을 return 받을 수 있다.

export default NextAuth({
  providers: [
    GoogleProvider({
      clientId: process.env.GOOGLE_CLIENT_ID,
      clientSecret: process.env.GOOGLE_CLIENT_SECRET,
    }),
  ],
  callbacks: [
    {
    async jwt({ token, account }) {
      if (account) {
        token.accessToken = account.access_token;
      }
      return token;
    },
    async session({ session, token }) {
      if (session) {
        session.accessToken = token.accessToken;
      }
      return session;
    },
  },
});

header 컴포넌트가 어느 페이지에나 존재하기 때문에 로그인 여부를 header에서 관리하기로 정했다. 여기서 useSession 훅을 통해 session data와 status를 확인 할 수 있다. 만약 소셜 로그인 상태라면 status를 console.log로 확인했을 때 "authenticated"가 찍히게 된다. 그래서 useEffect로 세션 상태를 확인해 로컬 토큰을 받아오기로 했다.

// header.js

import { useSession } from "next-auth/react";
.
.
.
const { data: sessionData, status: sessionStatus } = useSession();

useEffect(() => {
	if (sessionData && sessionStatus === "authenticated") {
      로컬토큰요청함수();
    }
}, [socialData,socialStatus]);

signOut

로그아웃은 더더 간단하다. 내 경우 로컬과 소셜을 같이 관리하기 위해 session data가 null이 아닐 경우, 소셜 로그인이기 때문에 signOut() 하도록 했다.

const logOutHandler = () => {
	if (sessionData) { 
		signOut();
	}
	로컬로그아웃함수();
  };
<button type="button" onClick={logOutHandler}>로그아웃</button>

error

[next-auth][error]CLIENT_FETCH_ERROR]

로컬에서 잘되다 배포 할 때 에러가 발생한다고.. ㅎㅎ..
환경변수에 NEXTAUTH_URL와 NEXTAUTH_SECRET를 반드시 넣어주어야 한다고 한다. NEXTAUTH_URL은 이미 있고, secret이 문제같았다.
바로 추가

// [...nextauth].js

secret: process.env.NEXTAUTH_SECRET

참고) https://next-auth.js.org/configuration/options#nextauth_secret

구글링 하다 보니 pages 폴더와 같은 레벨에 api 폴더가 존재하면 배포 시 에러가 발생할 수 있다고..! 혹시 다시 에러가 발생할까 싶어 같은 레벨에 있는 폴더 이름을 apis로 바꿔주고 경로를 모두 수정했다. 해결~

감사) https://velog.io/@awesome-hong/vercel

profile
절대로 할 수 있음

0개의 댓글