[공감병동 프로젝트] Google, Kakao Oauth with Next.js

ds-k.fe·2021년 12월 6일
0

공감병동 프로젝트

목록 보기
8/13
post-thumbnail

이번 프로젝트에서는 구글과 카카오 로그인만으로 구현을 해보기로 결정했다.
라이브러리를 배제하고, 공식 문서를 보면서 따라가기로 결정했다.
구현하는 방식 때문에 생각보다 많은 삽질을 했다.

OAuth 2.0 프로토콜

사용자가 어떤 서비스에 저장된 자신의 데이터를 다른 서비스에서 접근할 수 있도록 허락해주는 프로토콜을 말한다. 구글 뿐만 아니라, 페이스북, 트위터, 카카오 등이 이 프로토콜을 채택하고 있다.

기본적인 흐름을 정리해보자면 다음과 같다.(예시는 구글로 들겠다.)

  1. 사용자가 구글 인가 서버(Authorization Server)에 접속하여 로그인 후, 애플리케이션에서 요청하는 권한을 허용하는 인가 코드 전송 (유저가 구글로 로그인, 카카오 로그인 등을 클릭시)
  2. 1번에서 받은 인가 코드로 구글에게 Access Token, Refresh Token 등의 토큰 데이터 요청
  3. 토큰을 바탕으로 구글 서버에 user Data 요청

서비스에 적용

위의 흐름은 간단한 Oauth 2.0 프로토콜의 흐름인데, 이걸 서비스에 적용하는 방식은 정말 다양해 보였다. 이 글에서는 내가 적용한 방식을 바탕으로 적어보도록 하겠다.

1. 카카오, 구글에 애플리케이션 등록


각각의 페이지에 애플리케이션을 추가한다.

2. 인가 코드 받기

구글, 카카오로부터 인가 코드를 받기 위해서 각각의 API 문서를 참고해서 요청을 작성해주었다.
나는 a태그를 통해 해당 URL로 바로 요청을 보내는 방식을 선택하였다.

redirect_uri : 해당 인가코드를 어디로 리다이렉트 시켜서 받을지 적어준다. 해당 redirect_uri는 각각의 디벨로퍼 콘솔에다가 등록을 해 주어야 한다.
client_id : 1번에서 애플리케이션을 추가하면 얻을 수 있는 Id이다.
state : "로그인 요청과 콜백 간에 상태를 유지하기 위해 사용되는 임의의 문자열(정해진 형식 없음)
Cross-Site Request Forgery(CSRF) 공격으로부터 보호하기 위해 해당 파라미터 사용을 권장함" 이라고 되어 있는데, 나는 현재 하나의 컴포넌트에서 구글과 카카오 모두 로그인하고 있었기 때문에 인가 코드가 어디서 온 것인지 식별하는 용도로 state값을 사용하였다.

3. Redirect_uri에서 클라이언트로 인가 코드 전달

  • /oauth/google(or kakao)

    인가 코드를 요청할 때 나는 자체 API 서버로 redirect-uri를 지정하고 거기서 받은 code와 state값을 클라이언트 측으로 쿼리 파라미터와 함께 redirect해 주었다.

4. 인가 코드를 바탕으로 AccessToken 요청

  • LoginModal.tsx

    Next.js의 useRouter()를 사용해서 쿼리 파라미터를 받은 뒤 코드가 존재하게 될 경우, getSocialAccessToken을 실행하도록 했다.

5. AccessToken으로 Token 데이터 요청

  • Auth.tsx

    처음에 인가 코드 요청을 보낼때 함께 보낸 state를 통해 카카오와 구글의 로그인을 분기해주었고, 그를 통해 각각의 서버에 토큰 데이터를 요청했다.

API 문서에서 필요로 하는 값을 바탕으로 인가 코드를 바탕으로 토큰 데이터를 요청해 주었다.

6. TokenData를 서버에 전달

  • Auth.tsx

Token data를 각각 미리 만들어 놓은 서버 라우터로 POST 요청을 통해 전달해주었다.

7. TokenData를 바탕으로 유저 정보 요청 및 DB 등록

  • /oauth/google(or kakao)/login

Access Token을 헤더에 싣어 구글, 카카오 서버에 유저의 데이터를 요청하고 받아와서 DB에 써주었다.
그리고 자체 서비스 이용을 위한 AccessToken과 RefreshToken을 만들어 보내주었다.

구현 소감

자체 클라이언트와 서버 사이에서 어디로 Redirect 시킬지, 어디서 token을 요청할지에 대해 혼란이 많았다.
실제로 처음에 구현했던 것은 서버측에서 모든 요청을 마치고, 토큰을 만든 다음에 클라이언트로 쿼리를 통해 리다이렉트 시키는 방법을 했었는데, 아무리 봐도 AccessToken을 쿼리로 보내주는게 찝찝해서 다시 구성을 해보았다.
현재는
구글과의 인가 코드 받기, 액세스 토큰 받기와 같은 사전 과정(인증 로직 : 클라이언트 측)과,
그 토큰을 통해 유저 데이터를 받아 DB에 직접 쓰는 것(유저 데이터 로직: 서버측)이

양 측으로 잘 분리되어 있는 것 같아 만족스럽지만 향후 작업하다가 더 좋은 아이디어가 나오면 그 때 수정을 해봐도 좋을 것 같다.

1개의 댓글

comment-user-thumbnail
2021년 12월 13일

👍

답글 달기