Next
next-auth
- 간편한 소셜 로그인을 위한 라이브러리이다.
- 이전 게시글에서 작성했던
kakao API
의code, access token
을 사용하여 해당 유저의 정보를 가져오는 로직을 단순화하게 사용할 수 있다. - 또한 구글, 애플, 네이버, 카카오 등 라이브러리가 지원하는
auth
가 많기 때문에 사용이 간편하다. - 유저의 정보를 받아와
session
에 저장하고 이를 사용하여 유저의 정보를 활용한다.
사용법
1
npm i next-auth
next-auth
는session
을 활용하기 떄문에, 이를 전 범위적으로 사용할 Provider라는 개념이 존재한다.- 또한 각
social
로그인마다 로직을 간편하게 줄여줄 Provider가 존재하며 이 두 가지 개념은 다르다. - 우선 카카오의
Redirect URI
라는 개념이 존재하듯,next-auth
에도 이 개념이 존재한다. page route
를 활용한 방식이기 때문에 주솟값은 api/auth/callback/kakao(사용할 소셜 로그인 ex: kakao)로 고정된다.- 카카오의
Redirect URI
에 해당하는 부분에 본인의 도메인과next-auth
의 주솟값을 작성한다.1
http://localhost:3000/api/auth/callback/kakao
- Next 13 버전은 pages 디렉토리에서 app으로 바뀌었기 때문에, 버전에 따라 […nextauth].ts 안에 작성하는지, app/api/auth/[…nextauth]/route.ts 를 작성하는지가 나뉜다.
Next auth Provider
- 파일을 생성했다면 라이브러리에서 제공하는
NextAuth
를 활용하여provider
를 작성한다. NextAuth
는 요청과 응답을 담당한다.- 각 사용하려는
social login
에 맞는Provider
를 불러와 발급받은REST API
값과 클라이언트를 확인할ID
를 작성한다. - 카카오의 경우 clientId로는 REST API 키와 clientSecret으로는 [ 내 애플리케이션 > 앱 설정 > 요약 정보 > 기본 정보 ] 에 해당하는 앱 ID 를 작성한다.
1
2
3
4
5
6
7
8
9
10
11
12
// api/auth/[...nextauth].ts
import NextAuth from "next-auth";
import KakaoProvider from "next-auth/providers/kakao";
export default NextAuth({
providers: [
KakaoProvider({
clientId: process.env.KAKAO_CLIENT_ID!,
clientSecret: process.env.KAKAO_CLIENT_SECRET!,
}),
],
});
Credentials Provider
- 로그인을 하거나 회원 가입을 할 때,
form
에 작성한 사용자 입력 정보를 서버에 전송하듯이 동작한다. label, name, type
등의res
값으로 지정한 서버 주소로 전송하는 역할을 한다.- 마찬가지로 여려가지 옵션을 사용하거나
page, authorize
할 수 있다. - 경우에 따라
headers, body
를 작성하거나 작성한 값을 그대로 전송해도 된다.
1
2
3
4
5
6
7
8
9
10
11
12
export default function Credentials<
C extends Record<string, CredentialInput> = Record<string, CredentialInput>
>(options: UserCredentialsConfig<C>): CredentialsConfig<C> {
return {
id: "credentials",
name: "Credentials",
type: "credentials",
credentials: {} as any,
authorize: () => null,
options,
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
// api/auth/[...nextauth].ts
import NextAuth from "next-auth";
import KakaoProvider from "next-auth/providers/kakao";
import CredentialsProvider from "next-auth/providers/credentials";
export default NextAuth({
providers: [
CredentialsProvider({
name: "example", //여기에 작성한 name으로 signIn을 보냅니다.
credentials: {
username: {
label: "이메일",
type: "text",
placeholder: "이메일 주소 입력 요망",
},
password: { label: "비밀번호", type: "password" },
},
async authorize(credentials, req) {
const res = await fetch(`${process.env.NEXTAUTH_URL}/api/login`, {
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify({
username: credentials?.username,
password: credentials?.password,
}),
});
const user = await res.json();
console.log(user);
if (user) {
// Any object returned will be saved in `user` property of the JWT
return user;
} else {
// If you return null then an error will be displayed advising the user to check their details.
return null;
// You can also Reject this callback with an Error thus the user will be sent to the error page with the error message as a query parameter
}
},
})
,
KakaoProvider({
clientId: process.env.KAKAO_CLIENT_ID!,
clientSecret: process.env.KAKAO_CLIENT_SECRET!,
}),
],
});
credentials => signIn
- 위에서 작성한
credential name example
을 이용하여 지정한 주소로 작성한 메일과 비밀번호를 전송하여 로그인 처리를 한다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// Login.tsx
'use client'
...
import { signIn } from "next-auth/react";
export default function Login(){
const mailRef = useRef<HTMLInputElement>(null);
const passRef = useRef<HTMLInputElement>(null);
const signInHandler = async () => {
const result = await signIn("credentials", {
username: mailRef.current,
password: passRef.current,
redirect: true,
callbackUrl: "/",
});
}
return(
<React.Fragment>
<input id="mail" type="text" placeholder="이메일 입력" ref={mailRef}/>
<input id="pass" type="password" placeholder="비밀번호 입력" ref={mailRef}/>
<button type="button" onClick={signInHandler}>전송</button>
</React>
)
}
Session Provider
- 유저의 요청에
next-auth
의 실행 결과는session
에 담긴다. - 담긴
session
을 사용하기 위해,redux, recoil...
등의 전역 상태 라이브러리와 동일하게Provider
로 제공해주어야 한다. Provider
로 제공하고 나면 다른 컴포넌트에서useSession
을 사용해 저장된 회원 정보로 접근이 가능하다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// _app.tsx
import type { AppProps } from "next/app";
import { SessionProvider } from "next-auth/react";
export default function App({
Component,
pageProps: { session, ...pageProps },
}: AppProps) {
return (
<SessionProvider session={session}>
<Component {...pageProps} />
</SessionProvider>
);
}
1
2
3
4
5
6
7
8
9
10
11
12
// example.tsx
import { useSession } from "next-auth/react";
export default function Example(){
const {data: session} = useSession();
return(
<React.Fragment>
{data && <image src={data.profileImg}/>}
</React>
)
}