이번 프로젝트 소셜 로그인에 NextAuth를 적용해 보려고 한다. 공식 문서로 기본 개념 익히고 코드 짜 보면 좋을 것 같아서 혼자 간단하게 번역해 보면서 정리~!
NextAuth.js는 Next.js 애플리케이션을 위한 완벽한 오픈소스 인증 솔루션
NextAuth.js는 DB 있이/없이 사용될 수 있다!
MySQL, Postgres, SQL Server, MongoDB, SQLite 를 위해 내장된 지원+) 이메일 회원가입은 일회성 인증 토큰을 저장하도록 구성된 데이터베이스 필요함
고급 옵션을 사용하면 로그인이 허용되는 계정 제어, JSON 웹 토큰 인코딩 및 디코딩을 처리하는 고유한 루틴을 정의하고, 사용자 정의 쿠키 보안 정책 및 세션 속성을 설정할 수 있으므로, 로그인 할 수 있는 사람과 세션이 얼마나 자주 재검증 되어야 하는지를 제어할 수 있다!
우리 프로젝트는 이미 개발 초기 단계이기 때문에, 이미 존재하는 프로젝트의 경우에 어떻게 NextAuth.js를 적용하는지만 살펴보자.
npm install next-auth
✔️ 만약 TypeScript를 사용하고 있다면, NextAuth.js의 패키지 내에 타입 정의가 함께 제공된다.
프로젝트에 NextAuth.js를 추가하려면, pages/api/auth에 [...nextauth].js라는 파일을 생성해야 한다.(아마 공식 문서는 Page Router 기준인 것 같다.) 이것은 모든 전역 NextAuth.js 설정과, NextAuth.js를 위한 dynamic route handler를 포함하고 있다.
만약 App Router가 사용되는 Nextjs 13.2 버전 이상을 사용하고 있다면, 우리 가이드를 참고해 새로운 Route Handlers를 사용하여 초기 설정을 한다.
// /app/api/auth/[...nextauth]/route.ts
import NextAuth from "next-auth"
const handler = NextAuth({
...
})
export { handler as GET, handler as POST }
↑ App Router 가이드를 참고하면 이런 식이지만, 공식 문서 Getting Started는 일단 Page Router 기준으로 설명되어 있어서 앞으로의 코드는 Page Router 기준으로 작성해 보도록 하겠다.
// pages/api/auth/[...nextauth].js
import NextAuth from "next-auth"
import GithubProvider from "next-auth/providers/github"
export const authOptions = {
// Configure one or more authentication providers
providers: [
GithubProvider({
clientId: process.env.GITHUB_ID,
clientSecret: process.env.GITHUB_SECRET,
}),
// ...add more providers here
],
}
export default NextAuth(authOptions)
/api/auth/*(signIn, callback, signOut, etc)에 대한 모든 요청은 자동적으로 NextAuth.js에 의해 처리된다. 참고로 Provider에는 NaverProvider와 KakaoProvider도 있다!
공유 세션 state 설정
useSession을 먼저 사용하려면, 애플리케이션의 최상위 수준에서 세션 컨텍스트 <SessionProvider />가 있어야 한다.
// pages/_app.jsx
import { SessionProvider } from "next-auth/react"
export default function App({
Component,
pageProps: { session, ...pageProps },
}) {
return (
<SessionProvider session={session}>
<Component {...pageProps} />
</SessionProvider>
)
}
App Router에서는 아마 layout.tsx에 해당되지 않을까 싶다...(확실치않음)
useSession의 인스턴스는 그 다음 세션 data와 status에 접근할 것이다. <SessionProvider /> 또한 세션을 업데이트하고 브라우저 탭과 window 간에 동기화하는 작업을 담당한다.
NextAuth.js client의 useSession() React Hook은 누가 로그인 했는지 확인하기 위한 가장 쉬운 방법이다!
// components/login-btn.jsx
import { useSession, signIn, signOut } from "next-auth/react"
export default function Component() {
const { data: session } = useSession()
if (session) {
return (
<>
Signed in as {session.user.email} <br />
<button onClick={() => signOut()}>Sign out</button>
</>
)
}
return (
<>
Not signed in <br />
<button onClick={() => signIn()}>Sign in</button>
</>
)
}
useSession 훅을 통해 로그인 데이터에 접근할 수 있는 것 같다. 참고로 useSession 훅은 애플리케이션의 어디에서든 사용할 수 있다고 한다!
API Route를 보호하기 위해, getServerSession()을 사용할 수 있다.
// pages/api/restricted.js
import { getServerSession } from "next-auth/next"
import { authOptions } from "./auth/[...nextauth]"
export default async (req, res) => {
const session = await getServerSession(req, res, authOptions)
if (session) {
res.send({
content:
"This is protected content. You can access this content because you are signed in.",
})
} else {
res.send({
error: "You must be signed in to view the protected content on this page.",
})
}
}
NextAuth.js Callbakcs 사용
NextAuth.js를 사용하면 내장 callbacks을 통해 인증 플로우의 다양한 부분에 연결할 수 있다.
예를 들어, 로그인에서 프론트엔드(client side)로 값을 전달하려고 할 때, 다음과 같이 session과 jwt의 조합을 사용할 수 있다!
// pages/api/auth/[...nextauth].js
...
callbacks: {
async jwt({ token, account }) {
// Persist the OAuth access_token to the token right after signin
if (account) {
token.accessToken = account.access_token
}
return token
},
async session({ session, token, user }) {
// Send properties to the client, like an access_token from a provider.
session.accessToken = token.accessToken
return session
}
}
...
이제 getSession이나 useSession을 호출할 때마다, 반환되는 객체는 accessToken 값을 포함한다.
// components/accessToken.jsx
import { useSession, signIn, signOut } from "next-auth/react"
export default function Component() {
const { data } = useSession()
const { accessToken } = data
return <div>Access Token: {accessToken}</div>
}
NextAuth.js 내장 providers나 custom provider를 통해 OAuth provider를 사용하고 있다면, provider 세팅에 callback URL을 설정해줘야 한다. 각 provider는 "Configuration" 섹션을 가진다. 여기 참고
사이트를 배포할 때, NEXTAUTH_URL 환경 변수를 웹 사이트의 표준 URL로 설정하라!
NEXTAUTH_URL=https://example.com
✨ 음 뭔가 어떤 개념인지 대충~?은 알 것 같다. 우리 프로젝트에서는 카카오 소셜 로그인을 구현할 것 같은데 관련 링크도 찾아봐야겠다😌