한국에서는 꼭!? 카카오 로그인되야 하나? 몰라 ㅋㅋㅋ 일단 해보자. 제목에 #1 달아놨는데 뭔지 알겠지? ㅋㅋ 한번에 안끝날거 같네? ㅋ 뭐 카카오 문제는 아닌거 같은데 뭔가 삐그덕 거려. 시작해보자구.
카카오 로그인 사용하려면 우선 https://developers.kakao.com/ 에 로그인 해야해. 👇👇👇
뭐해! 애플리케이션 추가 안 누르고 ㅎㅎㅎ 앱 아이콘 대강 선택하고, 앱 이름도 넣고 사업자 명도 넣고~ 없다고? 아무거나 넣어 ㅋㅋㅋ 그리고 저장!
그러면 앱 키들이 주르륵 보이고, 그중에 REST API KEY 키는 Client id로 nextauth에서 사용할거니까 그렇게 알아두시고~~ 조 아래 플랫폼 설정하기를 눌러서 웹 프로젝트라고 알려주자구.
가장 하단에 웹 플랫폼 등록하기 눌르고 그 다음 사이트 도메인 입력하자구. 테스트니까 http://localhost:3000 으로 해야지. 그리고 저장.
도메인을 설정하고나면 아래 화면처럼 설정한게 보이는데 그 아래 Redirect URI 등록해야 함. 등록하기 눌러서 이동.
아래 상태를 OFF -> ON 으로 변경하고 아래 Redirect URI를 눌러서 Redirect URI도 등록하자구.
Redirect URI는 http://localhost:3000/api/auth/callback/kakao 를 입력.
이제 설정은 거의 끝났어. 이제 nextauth에서 카카오 rest api에 접근하기 위해 필요한 client id, client secret을 얻어와야 .env.local 파일에 넣어줄겨. 아까 말했지? rest api 키가 client id고 client secret은 내 애플리케이션 -> 제품 설정 -> 카카오 로그인 -> 보안 탭에서 찾을 수 있어.
nextauth에서 process.env.KAKAO_CLIENT_ID 이런식으로 읽어올 수 있도록 아래와 같이 env 파일에 입력합시다. KAKAO_AK는 app admin key 임 ㅋㅋ 미리 알려줌 ㅋ
//.env.local
KAKAO_CLIENT_ID = "xxxxxxxxxxxxxxxxxxxx니들거입력xxx"
KAKAO_CLIENT_SECRET = "xxxxxxxxxxxxxxxxx니클라이언트비밀입력xxx"
KAKAO_AK="xxxxxxxxxxx이건앱어드민입력혀미리알랴줌xxx"
자 이제 기본적인 설정은 끝났음. 이러면 로그인할 때 사용자 정보는 ID만 넘어오게 될거야.
어차피 github 주소를 공유하긴 할건데 여기에 계속 덮어쓸거라 코드가 글이랑 다를 수 있어~ 그리고 계속 말하지만 난 내가 미리 만들어 놓은 next.js 기본 템플릿을 사용하고 있으니깐 참고하도록.👇👇
2022.06.14 - [Next.js] - Next.JS 프로젝트 기본 템플릿 만들기#1
자 이제 코드 짜자 ㅋㅋㅋ nextauth는 뭐 똑같지. pages/api/auth 폴더에 [...nextauth].ts 이름으로 파일 생성 -> 아래와 같이 입력. 게providers 는 기본으로 들어가있어야 하는 옵션이고, 그 다음에 callbacks 옵션 있는데 음.. nextauth의 카카오는 다른 소셜로그인 provider랑은 좀 다르게 -_-;;; 음... session.user에.. 유저 정보가 없더라고 으하하하하 ㅋㅋㅋ 그래서 token.sub를 읽어와서 session에 넘겨 주려고 session callback을 추가했어.
//pages/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 as string,
clientSecret: process.env.KAKAO_CLIENT_SECRET as string,
}),
],
callbacks: {
async session({ session, token, user }) {
// Send properties to the client, like an access_token from a provider.
session.user.id = token.sub as string;
// console.log("token", token);
return session;
},
},
});
types/next-auth.d.ts 파일을 만들어서 아래와 같이 입력 -> 하면 session 타입 에러가 사라짐 ㅎ
//types/next-auth.d.ts
import NextAuth from "next-auth";
declare module "next-auth" {
/**
* Returned by `useSession`, `getSession` and received as a prop on the `SessionProvider` React Context
*/
interface Session {
user: {
id: string;
email: string;
};
}
}
이제 useSession 훅 사용하기 위해서 _app.tsx에다가 SessionProvider를 추가해보자구. 귀찮으니까 _app.tsx 전부 👇 SessionProvider 부분만 참고하면 될 듯.
// _app.tsx
import * as React from "react";
import Head from "next/head";
import { AppProps } from "next/app";
import { ThemeProvider } from "@mui/material/styles";
import CssBaseline from "@mui/material/CssBaseline";
import { CacheProvider, EmotionCache } from "@emotion/react";
import theme from "../src/theme";
import createEmotionCache from "../src/createEmotionCache";
import { NextPage } from "next";
//for kakao authentication using next-auth
import { SessionProvider } from "next-auth/react";
// Client-side cache, shared for the whole session of the user in the browser.
const clientSideEmotionCache = createEmotionCache();
interface MyAppProps extends AppProps {
emotionCache?: EmotionCache;
Component: NextPageWithLayout;
}
/*For Per-page layout! */
type NextPageWithLayout = NextPage & {
getLayout?: (page: React.ReactElement) => React.ReactNode;
};
export default function MyApp(props: MyAppProps) {
const {
Component,
emotionCache = clientSideEmotionCache,
pageProps: { session, ...pageProps },
} = props;
const getLayout = Component.getLayout ?? ((page) => page);
return (
<SessionProvider session={session}>
{getLayout(
<CacheProvider value={emotionCache}>
<Head>
<meta
name="viewport"
content="initial-scale=1, width=device-width"
/>
</Head>
<ThemeProvider theme={theme}>
{/* CssBaseline kickstart an elegant, consistent, and simple baseline to build upon. */}
<CssBaseline />
{/* <GlobalStyles /> */}
<Component {...pageProps} />
</ThemeProvider>
</CacheProvider>
)}
</SessionProvider>
);
}
이제 로그인으로 넘어갈 버튼을 만들어보자구. 난 이미 components 폴더에 만들어 놓은 MyButton.tsx를 수정해서 만들었어. 보면 특별한 건 없어. signIn, signOut 사용해서 로그인, 로그아웃하는 거지. 그런데 카카오도 다른 소셜로그인 공급자와 nextauth는 session에서만 logout을 하고 서버에서는 logout을 하지 않는 것 같더라고. 그래서 signout에 callback 옵션줘서 session 로그아웃에 성공하면 callback을 실행시켜서 서버 로그아웃을 시키는 거지. ㅎㅎㅎ 나 설명이 더럽네 ㅋ 이해안가면 댓글 달어 ㅋ
import React, { useEffect } from "react";
import { Button, ButtonProps } from "@mui/material";
import tw, { css, styled } from "twin.macro";
import { useSession, signIn, signOut } from "next-auth/react";
const MyButton = styled(Button)((props: ButtonProps) => [
tw`
text-blue-400
border-purple-500
text-5xl
shadow-md
rounded-xl
`,
]);
const LoginButtonBox: React.FC<any> = () => {
const { data: session } = useSession();
useEffect(() => {
console.log("user:", session?.user);
}, [session]);
if (session) {
return (
<>
Signed in as {session.user.id} <br />
<MyButton
onClick={() => {
// console.log("session id:", session.id);
signOut({
redirect: true,
callbackUrl: `http://localhost:3000/api/auth/serverlogout?userId=${session.user.id}`,
});
}}
>
Sign out
</MyButton>
</>
);
}
return (
<>
Not signed in <br />
<MyButton onClick={() => signIn()}>Sign in</MyButton>
</>
);
};
export default LoginButtonBox;
위에서 지정한 서버 로그아웃 callback용 api를 하나 만들자고 원래는 res.redirect로 하려고 했는데 redirect에는 header를 설정하지 못하나봐. 그래서 axios 설치해서 axios로 카카오 logout api를 호출했어. 카카오 로그아웃 rest api는 두 가지가 있는데 여기서는 그냥 admin key하고 user id 사용하는 방식을 사용했어.
//pages/api/auth/serverlogout.ts
import type { NextApiRequest, NextApiResponse } from "next";
import axios from "axios";
async function handleLogout(req: NextApiRequest, res: NextApiResponse) {
// req.query will return {userId:xxxxxxxxx}
// console.log("request query:", req.query);
const result = await axios.post(
`https://kapi.kakao.com/v1/user/logout?target_id_type=user_id&target_id=${req.query.userId}`,
{},
{
headers: {
Authorization: `KakaoAK ${process.env.KAKAO_AK}`,
"Content-Type": "application/x-www-form-urlencoded",
},
}
);
if (result.status == 200) {
//logged out successfully
res.redirect("/");
}
}
async function serverlogout(req: NextApiRequest, res: NextApiResponse) {
try {
await handleLogout(req, res);
} catch (error) {
console.error(error);
res.status(400).end(error);
}
}
export default serverlogout;
카카오 로그아웃에 필요한 옵션이나 설명은 공식문서를 참고하자! 👇👇
https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api
아휴 길다. 이제 다 한거 같은데? ㅎㅎ 테스트 해보면 아래처럼 다행이 로그인이 잘 동작하는 것 같아.
하!지!만! 다시 로그인을 해보면 카카오 로그인없이 로그인이 그냥 되네.... 음... 이건 내가 의도한 동작이 아냐.. 음... 이것 때문에 하루 종일 난리치다가 ㅋㅋㅋ 이건 아무래도 오늘 안될 것 같아. #2 로 넘어가서 계속해볼게 ㅋㅋ 자 다들 화이팅 안녕!
github 주소 👉👉👉https://github.com/peter-bang/nextauth-kakao-authentication
'Next.js > nextauth' 카테고리의 다른 글
next-auth cognito login (0) | 2022.06.23 |
---|---|
next.js + AWS amplify auth login (0) | 2022.06.21 |
nextauth + firebase authentication #2 (2) | 2022.06.03 |
nextauth + firebase authentication #1 (1) | 2022.06.02 |
nextauth + firebase authentication (0) | 2022.06.02 |