Don't think! Just do it!

종합 IT 기술 정체성 카오스 블로그! 이... 이곳은 어디지?

Next.js/nextauth

nextauth 카카오 로그인 #1

방피터 2022. 7. 13. 19:25

한국에서는 꼭!? 카카오 로그인되야 하나? 몰라 ㅋㅋㅋ 일단 해보자. 제목에 #1 달아놨는데 뭔지 알겠지? ㅋㅋ 한번에 안끝날거 같네? ㅋ 뭐 카카오 문제는 아닌거 같은데 뭔가 삐그덕 거려. 시작해보자구.

카카오 로그인 사용하려면 우선 https://developers.kakao.com/ 에 로그인 해야해. 👇👇👇

애플리케이션 추가

뭐해! 애플리케이션 추가 안 누르고 ㅎㅎㅎ 앱 아이콘 대강 선택하고, 앱 이름도 넣고 사업자 명도 넣고~ 없다고? 아무거나 넣어 ㅋㅋㅋ 그리고 저장!

새 애플리케이션 만들기

그러면 앱 키들이 주르륵 보이고, 그중에 REST API KEY 키는 Client id로 nextauth에서 사용할거니까 그렇게 알아두시고~~ 조 아래 플랫폼 설정하기를 눌러서 웹 프로젝트라고 알려주자구.

플랫폼 추가

가장 하단에 웹 플랫폼 등록하기 눌르고 그 다음 사이트 도메인 입력하자구. 테스트니까 http://localhost:3000 으로 해야지. 그리고 저장.

도메인 입력

도메인을 설정하고나면 아래 화면처럼 설정한게 보이는데 그 아래 Redirect URI 등록해야 함. 등록하기 눌러서 이동.

Redirect URI 입력

아래 상태를 OFF -> ON 으로 변경하고 아래 Redirect URI를 눌러서 Redirect URI도 등록하자구.

Redirect URI 입력 화면

Redirect URI는 http://localhost:3000/api/auth/callback/kakao 를 입력.

Redirect URI

이제 설정은 거의 끝났어. 이제 nextauth에서 카카오 rest api에 접근하기 위해 필요한 client id, client secret을 얻어와야 .env.local 파일에 넣어줄겨. 아까 말했지? rest api 키가 client id고 client secret은 내 애플리케이션 -> 제품 설정 -> 카카오 로그인 -> 보안 탭에서 찾을 수 있어.

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

 

Next.JS 프로젝트 기본 템플릿 만들기#1

nextjs 말고도 이런 저런 것들이 많이 필요한 것 같아. 기본적으로 ui framwork도 하나 있어야 할 것 같고 tailwindcss도 사용하고 싶고 storybook도 사용하면 좋을 것 같고 .env.local, .npmrc, .nvmrc 파일도 만..

engschool.tistory.com

 

자 이제 코드 짜자 ㅋㅋㅋ  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

 

Kakao Developers

카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.

developers.kakao.com

아휴 길다. 이제 다 한거 같은데? ㅎㅎ 테스트 해보면 아래처럼 다행이 로그인이 잘 동작하는 것 같아. 

카카오 로그인

하!지!만! 다시 로그인을 해보면 카카오 로그인없이 로그인이 그냥 되네.... 음... 이건 내가 의도한 동작이 아냐.. 음... 이것 때문에 하루 종일 난리치다가 ㅋㅋㅋ 이건 아무래도 오늘 안될 것 같아. #2 로 넘어가서 계속해볼게 ㅋㅋ 자 다들 화이팅 안녕!

 

github 주소 👉👉👉https://github.com/peter-bang/nextauth-kakao-authentication

 

GitHub - peter-bang/nextauth-kakao-authentication: kakao authentication example using nextauth on next.js web application

kakao authentication example using nextauth on next.js web application - GitHub - peter-bang/nextauth-kakao-authentication: kakao authentication example using nextauth on next.js web application

github.com

 

반응형

'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