likeornament 님의 블로그
Auth.js(NextAuth.js) 사용법 본문
Auth.js(이전 명칭: NextAuth.js)는 Next.js에서 인증 시스템을 구현하기 위해 설계된 오픈 소스 라이브러리다.
장점
- Login Provider로 구글, 네이버, 카카오 등의 소셜 로그인 등을 지원하기에 간편 로그인을 쉽게 구현할 수 있다.
- Credential Provider로 기본적인 로그인, 로그아웃을 지원하고 로그인에 따른 쿠키를 관리하기 쉽다.
위의 장점들 때문에 프로젝트에서 인증 시스템을 구현할 때 Auth.js를 사용했다.
이제 설치 방법과 구성요소, 사용법에 대해 알아보자.
1. 설치
$ npm i next-auth@beta
- 위의 명령어로 auth.js 설치한다.
- @auth/core 관련 작업은 Auth.js가 알아서 처리하기에 굳이 직접 설치할 필요는 없다.
npx auth secret
- 터미널에 다음과 같이 입력하면 서명(Signing)과 암호화(Encryption) 관련 작업에 사용되는 키를 생성해 준다.
AUTH_SECRET=위에서 생성된 값 넣기
- .env 파일에 AUTH_SECRET의 값으로 넣어준다.
2. 구성 요소
NextAuth() 호출로 Next.js 애플리케이션에서 인증 처리를 담당하는 함수들을 반환 받을 수 있다.
1. handlers
- 인증 처리 과정에서 GET, POST 요청을 처리하는 핸들러.
- GET: 인증상태 확인, 로그인 페이지로의 리다이렉션 등.
- POST: 로그인 시 사용자 인증 로직 처리
2. auth
- Auth.js의 핵심 인증 함수로, 사용자 세션 및 JWT 처리를 담당.
3. signIn
- 로그인 프로세스를 시작하는 함수.
- 클라이언트에서 인증 페이지로 리다이렉션하거나, API 호출로 로그인 처리를 트리거한다.
4. signOut
- 현재 로그인 한 사용자의 세션을 종료하는 함수.
- 서버와 통신하여 세션을 삭제하고 로그아웃 상태를 유지.
3. 사용 방법
1) [...nextauth]/route.ts
export { GET, POST } from '@/auth';
- 프로젝트에 Auth.js를 추가하려면 app/api/auth에 API 라우터인 [...nextauth]를 추가해야 한다.
- 그 아래에 route.ts 파일을 만들어서 위의 코드를 작성한다.
- 이 코드는 src/auth.ts 파일에 정의된 GET, POST 핸들러를 가져와서 route.ts 파일을 통해 Next.js에 등록한다.
2) middleware.ts
import { auth } from "./auth"
import { NextResponse } from "next/server"
import type { NextRequest } from "next/server"
export async function middleware(request: NextRequest) {
// 세션 검증
const session = await auth();
// 세션이 없으면 로그인 페이지로 리다이렉트
if (!session) {
console.log('No active session for protected route');
return NextResponse.redirect(new URL('/login', request.url));
}
return NextResponse.next();
}
export const config = {
matcher: ['/post', '/likes', '/notice', '/myPage'],
}
- middleware는 next.js에서 페이지를 렌더링하기 전에 서버 측에서 실행되는 함수이다.
- middleware.ts는 src 폴더에 포함되거나, app과 같은 수준의 트리에 존재해야 한다.
- config에 정의된 matcher에 해당되는 경로에 진입하면, 렌더링 이전에 middleware() 함수가 호출된다.
=> 즉, 위의 코드는 matcher에 정의된 경로로 진입할 때 세션이 있는지 확인하고, 없다면 "/login" 경로로 리다이렉션한다.
3) src/auth.ts
import NextAuth from "next-auth";
import CredentialsProvider from "next-auth/providers/credentials";
import { cookies } from "next/headers";
import cookie from 'cookie';
export const {
handlers: { GET, POST },
auth,
signIn,
} = NextAuth({
pages: {
signIn: '/login',
newUser: '/register',
},
callbacks: {
jwt({ token}) {
return token;
},
session({ session}) {
return session;
},
},
providers: [
CredentialsProvider({
async authorize(credentials) {
const authResponse = await fetch(`${process.env.NEXT_PUBLIC_BACKEND_API_SERVER}/login`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
loginId: credentials.username,
pw: credentials.password,
}),
});
let setCookie = authResponse.headers.get('set-cookie');
if (setCookie) {
const parsed = cookie.parse(setCookie);
cookies().set('JSESSIONID', parsed['JSESSIONID'], {
...parsed,
maxAge: 1800, //30분
path: '/'
});
}
if (!authResponse.ok) {
console.error('Login failed:', authResponse.statusText);
return null;
}
const responseText = await authResponse.text();
let user;
try {
user = JSON.parse(responseText);
} catch (error) {
console.error('Failed to parse JSON:', error);
return null;
}
if (!user.loginId || !user.email || !user.name || !user.profilePath) {
console.error('User object is missing required properties:', user);
return null;
}
return {
id: user.loginId,
email: user.email,
name: user.name,
image: user.profilePath,
...user,
};
}
}),
],
session: {
maxAge: 1800
}
});
- auth.ts는 Auth.js의 설정 파일이다.
- 인증 로직, 세션 관리, providers 등을 설정한다.
export const {
handlers: { GET, POST },
auth,
signIn,
} = NextAuth({...});
- NextAuth() 함수로부터 handlers(GET, POST), auth, signIn을 반환받는다.
pages: {
signIn: '/login',
newUser: '/register',
}
- 사용자에게 보여줄 로그인 페이지(signIn)와 회원가입 페이지(newUser) 경로를 설정한다.
- 해당 설정을 하지 않을 경우, Auth.js에서 제공하는 기본 페이지들이 생성된다.
callbacks: {
jwt({ token }) {
return token;
},
session({ session }) {
return session;
},
}
- callbacks는 인증 및 세션 관리 중 호출되는 각 핸들러를 지정한다.
- jwt: JWT가 생성되거나 업데이트될 때 호출되며 반환값은 쿠키에 저장된다.
- session: 위의 jwt가 반환하는 token을 받아 세션이 확인될 때마다 호출된다.
=> 브라우저에 저장된 next-auth.session-token이라는 이름의 쿠키에 저장된 사용자 정보를 클라이언트에서 수정할 때 사용
CredentialsProvider({
async authorize(credentials) { ... }
}),
- CredentialsProvider는 아이디와 비밀번호 등을 사용하여 사용자를 인증하는 프로바이더이다.
- 사용자 인증을 위한 백엔드 서버와 통신해서, 인증이 성공한 경우 사용자 객체를 반환한다.
let setCookie = authResponse.headers.get('set-cookie');
if (setCookie) {
const parsed = cookie.parse(setCookie);
cookies().set('JSESSIONID', parsed['JSESSIONID'], {
...parsed,
maxAge: 1800,
path: '/'
});
}
- 백엔드로부터 로그인 성공 시 set-cookie 헤더로 세션 쿠키를 전달 받는다.
- 헤더에서 쿠키를 가져와 Next.js의 cookies() API를 사용하여 세션 쿠키를 설정한다.
const responseText = await authResponse.text();
let user;
try {
user = JSON.parse(responseText);
} catch (error) {
console.error('Failed to parse JSON:', error);
return null;
}
- 서버로부터 받은 응답 본문을 JSON 형식으로 파싱하며, 파싱 실패 시 null을 반환
return {
id: user.loginId,
email: user.email,
name: user.name,
image: user.profilePath,
...user,
};
- 로그인 성공 시 id, email, name, image라는 정해진 속성으로 유저 정보를 반환해야 한다.
import { signIn } from "next-auth/react";
const handleLogin = () => {
signIn("credentials", {
username: "user",
password: "pass",
callbackUrl: "/home",
});
};
- 로그인하는 방법은 next-auth/react에서 signIn 함수를 불러와 위의 코드처럼 사용하면 된다.
import { signOut } from "next-auth/react";
const handleLogout = () => {
signOut({ callbackUrl: "/login" });
};
- 로그아웃은 signOut 함수를 불러와 위의 코드처럼 사용하면 된다.
4) useSession 사용법
'use client';
import { SessionProvider } from "next-auth/react";
type Props = ({
children: React.ReactNode;
});
export default function AuthSession({ children }: Props) {
return <SessionProvider>{children}</SessionProvider>;
}
- 로그인한 유저의 정보를 가져오려면 useSession() 훅을 사용하면 된다.(클라이언트 컴포넌트에서만 사용 가능)
- useSession() 훅을 사용하기 위해선 먼저 AuthSession.tsx를 만들어야 한다.
<AuthSession>{children}</AuthSession>
- 루트 레이아웃의 children을 이렇게 AuthSession으로 감싸야 프로젝트에서 useSession을 사용할 수 있다.
const { data: session, status } = useSession();
- useSession은 세션 정보와 세션 상태를 반환한다.
- data(세션 정보): 로그인된 사용자의 정보를 담고 있다.
- status(세션 상태): "loading", "authenticated", "unauthenticated"의 세 가지 상태를 나타내는 문자열
import {auth} from "@/auth";
const session = await auth();
- 서버 컴포넌트에서 세션 정보를 사용하고 싶다면 auth() 함수를 사용하면 된다.
'공부' 카테고리의 다른 글
Tanstack Query(React Query)에 대해 알아보자 (0) | 2024.12.31 |
---|