NextAuth: 소셜 로그인 및 세션 처리
2024.05.19
next-auth란
next-auth는 다양한 로그인 방식을 제공하는 인증 라이브러리이다. 다양한 소셜 로그인 방식을 제공하며, 이메일/비밀번호 로그인 방식도 제공한다.
공식 문서에는 다음 3가지 특징이 있다고 한다.
- Easy 여러 로그인 방식을 플러그인 형식으로 제공하며, 간단한 설정으로 사용할 수 있다.
- Flexible 서버리스용으로 구축되어서 어디에서든 사용할 수 있게 한다.
- Secure 서명되고 접두사가 붙은 서버 전용 쿠키, HTTP POST + CSRF 토큰 검증, JWS/JWE/JWK를 사용한 JWT, 탭 동기화, 자동 재검증, 연결 유지 등 기능을 제공한다. 클라이언트측 코드에 의존하지 않는다.
설치하기
database로는 무료로 사용가능한 Firebase를 사용했다. next-auth에서는 firebase adapter를 제공하기에 쉽게 개발을 할 수 있다.
소셜 로그인으로는 Google과 Kakao로그인을 사용했다.
- next-auth 설치
pnpm install next-auth firebase-admin @auth/firebase-adapter
- api 만들기
import { authOptions } from '@/utils';
import NextAuth from 'next-auth/next';
const handler = NextAuth(authOptions);
export { handler as GET, handler as POST };
import { AuthOptions } from 'next-auth';
import { FirestoreAdapter } from '@auth/firebase-adapter';
import { cert } from 'firebase-admin/app';
import { Adapter } from 'next-auth/adapters';
import GoogleProvider from 'next-auth/providers/google';
import KakaoProvider from 'next-auth/providers/kakao';
export const authOptions: AuthOptions = {
providers: [
KakaoProvider({
clientId: process.env.KAKAO_CLIENT_ID!,
clientSecret: process.env.KAKAO_CLIENT_SECRET!,
}),
GoogleProvider({
clientId: process.env.GOOGLE_CLIENT_ID!,
clientSecret: process.env.GOOGLE_CLIENT_SECRET!,
}),
],
adapter: FirestoreAdapter({
credential: cert({
projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID,
clientEmail: process.env.FIREBASE_CLIENT_EMAIL,
privateKey: process.env.FIREBASE_PRIVATE_KEY!.replace(/\\n/g, '\n'),
}),
}) as Adapter,
callbacks: {
session({ session, token, user }) {
session.id = user.id;
return session;
},
},
secret: process.env.NEXTAUTH_SECRET,
};
오류 error Can't resolve 'net' 절대 경로로 api에 사용되는 next-auth파일을 utils폴더에 넣어서 내보내니 client, server에서 둘다 사용가능한 파일이 되었다. nextjs 에서는 server와 client를 나누어 주어서 authOptions를 내보낼때 client 전용 파일과 같이 내보내면 안된다.
import NextAuth from 'next-auth';
declare module 'next-auth' {
interface Session {
id: string;
}
}
next-auth에서 session에 id를 추가하기 위한 타입 선언
- 로그인 세션 사용하기
'use client';
import { Session } from 'next-auth';
import { SessionProvider } from 'next-auth/react';
interface ProvidersProps {
children: React.ReactNode;
session?: Session;
}
export function Providers({ children, session }: ProvidersProps) {
return <SessionProvider session={session}>{children}</SessionProvider>;
}
위 Provider를 루트 레이아웃에 추가하여 사용한다.
- 로그인과 로그아웃
import { signIn } from 'next-auth/react';
type LoginType = 'google' | 'kakao';
export const loginHandler = (variant: LoginType) => {
signIn(variant, { callbackUrl: '/' });
};
import { signOut } from 'next-auth/react';
// ...생략
reutnr (
<button onClick={() => signOut()}>로그아웃</button>
)
- 세션 처리
- client에서 로그인하고 session 확인하기
import { loginHandler } from '@/utils'; import { signOut, useSession } from 'next-auth/react'; const { data: session, status } = useSession(); <button onClick={() => loginHandler('google')}>구글 로그인</button> <button onClick={() => loginHandler('kakao')}>카카오 로그인</button> <button onClick={() => signOut()}>로그아웃</button>
- server에서 사용하는 방법 (비로그인시 페이지 자체를 접근을 막을 수 있다)
import { getServerSession } from "next-auth"; import { authOptions } from "@/utils/server"; export default async function Page() { const session = await getServerSession(authOptions); if (!session) { return redirect; } return; //... 생략 }
- Firebase에 저장 되는값 3개의 accounts, sessions, users 컬렉션이 생성된다.
- accounts
- sessions
- users
firebase key 발급
[프로젝트 설정] → [서비스 계정] → [새 비공개키 생성] 키 생성시 키를 가지고 있는 json파일을 다운로드 받을 수 있다.
firebase-admin에서 사용하는 다음 키 3개를 얻을 수 있다
- FIREBASE_PROJECT_ID
- FIREBASE_CLIENT_EMAIL
- FIREBASE_PRIVATE_KE
소셜 로그인 키 발급
kakao
- [내 애플리케이션] → [요약정보] → REST API 키 : KAKAO_CLIENT_ID
- [내 애플리케이션] → [보안] → 코드 : KAKAO_CLIENT_SECRET
- [내 애플리케이션] → [카카오로그인] → 활성화 ON 및 RedirectURL 등록
- [동의항목] *닉네임 및 이미지 등을 받기 위해서는 아래 내용 동의에서 추가할 수 있다
firebase를 사용하면 google 로그인 key를 발급 밥기 쉽다.
- 새 제공업체 구글 추가
- 웹 SDK 구성에서 구글 로그인 key를 얻을 수 있다
- GOOGLE_CLIENT_ID
- GOOGLE_CLIENT_SECRET
- RedirectURL 등록
-
구글 API 콘솔 클릭 (구글 콘솔로 이동)
-
OAuth 2.0 클라이언트 ID 클릭
-
Redirect URL 추가
-
*OAuth 동의 화면에서 구글 로그인시 받을 정보(닉네임,이미지 및 동의 화면)등을 수정할 수 있다