본문 바로가기
시작/TIL(Today I Learned)

231110 - 카카오 로그인 (feat. KOE010)

by 백씨네 2023. 11. 10.

카카오 로그인 토큰 받기

문제

카카오 로그인 중 2단계에 해당하는 토큰을 받아오는 과정에서 axios로는 정상적으로 받아오는데 fetch로는 받아오지 못하는 문제가 발생했다.
처음에 fetch를 사용했던 방법은

const url = `https://kauth.kakao.com/oauth/token`
const body = {
        grant_type: 'authorization_code',
        client_id: process.env.REST_API as string,
        redirect_uri: process.env.REDIRECT as string,
        code,
    }
const result = await fetch(url, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
        },
        body: JSON.stringify(body),
    })
const data = await result.json()

을 사용했다.

 

하지만 이 방법은 아래와 같은 오류(KOE010)를 발생했다.

{
  error: 'invalid_client',
  error_description: 'Bad client credentials',
  error_code: 'KOE010'
}

 

카카오 로그인 공식 문서를 보면 해당 오류는 클라이언트 시크릿(Client secret) 기능을 사용하는 앱에서 토큰 요청 시 client_secret 값을 누락했거나 잘못된 값을 전달한 경우 발생한다고 한다.

하지만 나는 클라이언트 시크릿 기능을 활성화하지 않은 상태이기 때문에 이 오류가 발생할 수 없다.

다른 방법

axios로 요청을 보내는 방법을 사용했더니 정상적으로 토큰을 받아왔다. 그래서 axios와 fetch의 차이점을 찾아보았다.

 

차이점

 

Content-Type과 요청 본문의 형식

 

카카오 API는 일반적으로 application/x-www-form-urlencoded 형식의 데이터로 요청을 받는다. axios를 사용할 때, 요청 본문은 자동으로 application/x-www-form-urlencoded 형식으로 변환됩니다. headers에서 설정한 Content-Type과 일치합니다.
반면, fetch를 사용할 때는 JSON.stringify(body)를 사용하여 요청 본문을 JSON 형식으로 변환합니다. 그러나 headers에서 설정한 Content-Type은 application/x-www-form-urlencoded이다.

그래서 형식이 맞지 않아 오류가 발생한 것이다. 형식을 맞춰 주기 위해서 fetch를 사용할 때는 URLSearchParams를 사용하여 요청 본문을 application/x-www-form-urlencoded 형식으로 변환해주어야 한다.

어떻게 보면 너무 어이없는 실수를 한 것 같다.

 

해결

  1. axios 방식
const url = `https://kauth.kakao.com/oauth/token`
const body = {
        grant_type: 'authorization_code',
        client_id: process.env.REST_API as string,
        redirect_uri: process.env.REDIRECT as string,
        code,
    }
const {data} = await axios.post(
    url,
    {
        grant_type: 'authorization_code',
        client_id: process.env.REST_API as string,
        redirect_uri: process.env.REDIRECT as string,
        code,
    },
    {
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
        },
    },
)
  1. fetch 방식
const url = `https://kauth.kakao.com/oauth/token`
const fetchBody = new URLSearchParams({
        grant_type: 'authorization_code',
        client_id: process.env.REST_API as string,
        redirect_uri: process.env.REDIRECT as string,
        code,
})

const result = await fetch(url, {
        method: 'POST',
        headers: {
            'Content-Type': 'application/x-www-form-urlencoded;charset=utf-8',
        },
        body: fetchBody,
    })
const data = await result.json()

댓글