Next에서는 주로, NextAuth라는 라이브러리를 사용해서 인증기능을 구현한다.
최근에는 NextAuth는 5버전으로 업데이트가 되면서 Auth.js로 명칭이 바뀌었다.
이 라이브러리는 SvelteKit, SolidStart 등 Next외의 라이브러리도 지원한다.
또한, Providers
를 제공하여 다양한 회사의 OAuth
를 쉽게 구현할 수 있다.
beta를 입력해야 최신버전으로 설치된다.
# npm
npm install next-auth@beta
# or yarn
yarn add next-auth@beta
명령어를 통해 랜덤한 AUTH_SECRET
에 사용할 랜덤한 문자열을 받는다.
npx auth secret
그럼 터미널에 AUTH_SECRET=1234135asd
와 같이 생성되는데 이를
.env.local
에 등록해준다.
AUTH_SECRET=1234135asd
명령어를 통해 생성해도 되지만, 임의로 작성해줘도 된다.
auth.ts 생성
auth.ts
파일을 최상단인src
폴더에 생성하고 다음과 같이 작성한다.
import NextAuth from "next-auth";
export const {
handlers: { GET, POST },
signIn,
signOut,
auth,
} = NextAuth({
providers: [],
});
route.ts 생성
/app/api/auth/[...nextauth]/route.ts
경로에 API Route가 사용할 파일인 route.ts
를 생성하고 다음과 같이 작성한다.
import { GET, POST } from "@/auth";
Catch-all Route
[...폴더이름]과 같이 작성하고 이렇게 작성하면 다음과 같이 이용할 수 있다.
예를 들어,app/shop/[...name]/page.ts
를 생성했을 때
/shop/a 와 /shop/a/b/c 와 /shop/b/d 는 모두 해당 라우트로 적용되어 보여진다.
middleware.ts 생성
Next에서 지원하는 middleware.ts
파일을 최상단인 src
폴더에 생성하고 다음과 같이 작성한다.
export { auth as middleware } from "@/auth" // 미들웨어 역할
export const config = { // 미들웨어를 적용할 라우트
matcher:[]
}
auth.ts에 작성된 providers에 Auth.js | Authentication을 참고하여 작성해준다.
서버 컴포넌트를 사용중이라면 src/auth.ts
에 정의되어 있는 SignIn
함수를 import 하여 로그인 기능을 구현한다
예시
import { signIn } from "@/auth.ts"
export function SignIn() {
return (
<form
action={async () => {
"use server"
await signIn()
}}
>
<button type="submit">Sign in</button>
</form>
)
}
클라이언트 컴포넌트를 사용중이라면 next-auth/react
에 정의되어 있는 SignIn 함수를 import하여 로그인 기능을 구현한다.
예시
import { signIn } from "next-auth/react"
export function SignIn() {
return <Button onClick={() => signIn()}>Sign In</Button>
}
로그아웃하기는 로그인하기와 유사하게 작성해주면 된다.
import { signOut } from "@/auth.ts"
export function SignOut() {
return (
<form
action={async () => {
"use server"
await signOut()
}}
>
<button type="submit">Sign Out</button>
</form>
)
}
import { signOut } from "next-auth/react"
export function SignOut() {
return <button onClick={() => signOut()}>Sign Out</button>
}
import { auth } from "@/auth"
export default async function UserAvatar() {
const session = await auth()
if (!session.user) return null
return (
<div>
<img src={session.user.img} alt="User Avatar" />
</div>
)
}
위 방식과 살짝 다른 부분이 있는데 SessionProvider
로 세션이 필요한 파일을 감싸주면 된다.
예시
// app/layout.tsx
import { SessionProvider } from "next-auth/react";
export default function RootLayout({ children }: Readonly<Props>) {
return (
<html lang='ko'>
<body className={inter.className}>
<SessionProvider>{children}</SessionProvider>
</body>
</html>
);
}
import { useSession } from "next-auth/react"
import { UserAvatar } from "@/app/_components/UserAvatar"
export default function Dashboard() {
const session = useSession()
return (
<nav>
<UserAvatar session={session} />
</nav>
)
}