본문 바로가기
Spring/Spring Boot

[Spring boot - OAuth2] Kakao Login 구현 #03

by seoyamin 2022. 11. 18.

0. 전체 Flow

오늘은  Step 2  부분을 구현해보고자 한다. 

 

①  Spring boot 서버에서 code를 이용해서 카카오 Auth 서버에 토큰 달라고 요청
②  code를 바탕으로 카카오 Auth 서버에서 토큰 발급
③  Spring boot 서버에서 토큰을 받으면 끝 !

 

 

1. GSON dependency 추가

Java에서 json을 다루는 라이브러리 중 하나인 gson을 이용해볼 것이다.

build.gradle에 gson dependency를 추가해준다.

 

// build.gradle

dependencies {
    ...
    
    implementation'com.google.code.gson:gson:2.8.7'

    ...
}

 

 

 

2. OAuthService 구현

♠  Kakao Developers Docs

우리는 결국 https://kauth.kakao.com/oauth/token 으로 POST 요청을 보내서 토큰을 발급받으면 된다.

카카오 공식 문서에 request, response와 관련된 형식이 안내되어 있다.

우리가 요청과 함께 보낼 Parameter들
우리가 받을 Response 값들

 

 

나는 어떤 분의 블로그 글을 참고하여 코드를 작성 및 공부하였다. 

( 출처 https://suyeoniii.tistory.com/79?category=858035 )

전체 코드를 한번 훑어보고, 하나하나 뜯어보며 이해해보자.

 

// OAuthService.java

package com.surveasy.surveasy.service;

import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import org.springframework.stereotype.Service;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;

@Service
public class OAuthService {

    public String getKakaoAccessToken(String code) {
        String access_Token = "";
        String refresh_Token = "";
        String reqURL = "https://kauth.kakao.com/oauth/token";

        try {
            URL url = new URL(reqURL);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();

            // POST 요청을 하기 위해 기본값이 false였던 setDoOutput 값을 true로 변경
            conn.setRequestMethod("POST");
            conn.setDoOutput(true);

            // POST 요청에 필요로 하는 파라미터 스트림을 통해 전송
            BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
            StringBuilder stringBuilder = new StringBuilder();
            stringBuilder.append("grant_type=authorization_code");
            stringBuilder.append("&client_id={REST_API_KEY}");
            stringBuilder.append("&redirect_uri={REDIRECT_URI}");
            stringBuilder.append("&code=" + code);
            bufferedWriter.write(stringBuilder.toString());
            bufferedWriter.flush();

            // 결과 코드가 200이면 성공
            int resCode = conn.getResponseCode();
            System.out.println("response CODE : " + resCode);

            // 요청을 통해 얻은 JSON 타입의 Response 데이터 읽어오기
            BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            String line = "";
            String result = "";

            while((line = bufferedReader.readLine()) != null) {
                result += line;
            }
            System.out.println("response BODY : " + result);

            // Gson 라이브러리에 포함된 클래스로 JSON 파싱 객체 생성
            JsonParser jsonParser = new JsonParser();
            JsonElement jsonElement = jsonParser.parse(result);

            access_Token = jsonElement.getAsJsonObject().get("access_token").getAsString();
            refresh_Token = jsonElement.getAsJsonObject().get("refresh_token").getAsString();

            System.out.println("access Token : " + access_Token);
            System.out.println("refresh Token : " + refresh_Token);

            bufferedReader.close();
            bufferedWriter.close();


        }  catch (IOException e) {
            e.printStackTrace();
        }

        return access_Token;
    }

}

 

 

2-1. 변수 설정

우리가 받아올 access token, response token 변수를 초기화 하고, 요청을 보낼 request URI 주소도 정의해놓는다. 

 

String access_Token = "";
String refresh_Token = "";
String reqURL = "https://kauth.kakao.com/oauth/token";

 

2-2. http connection 열기

2-1에서 정의한 reqest URI에 POST 요청을 보내기 위해 http connection을 정의하고,

사용을 위해 스위치를 켜준다. (setDoOutput 값을 false → true로 변경)

 

URL url = new URL(reqURL);
HttpURLConnection conn = (HttpURLConnection) url.openConnection();

// POST 요청을 하기 위해 기본값이 false였던 setDoOutput 값을 true로 변경
conn.setRequestMethod("POST");
conn.setDoOutput(true);

 

2-3.  POST 요청에 필요한 정보를 stream으로 가공해서 전송

reqURI에 grant_type, client_id, redirect_uri, code값을 보내면서 POST 요청을 한다. 

(code 값은 이전에 받아온 인가 코드)

 

// POST 요청에 필요로 하는 파라미터 스트림을 통해 전송
BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
StringBuilder stringBuilder = new StringBuilder();
stringBuilder.append("grant_type=authorization_code");
stringBuilder.append("&client_id={REST_API_KEY}");
stringBuilder.append("&redirect_uri={REDIRECT_URI}");
stringBuilder.append("&code=" + code);
bufferedWriter.write(stringBuilder.toString());
bufferedWriter.flush();

// 결과 코드가 200이면 성공
int resCode = conn.getResponseCode();
System.out.println("response CODE : " + resCode);

 

 

2-4.  요청 결과를 JSON 타입으로 읽어오기

stream으로 받아온 string 데이터들을 gson 라이브러리를 통해 JSON Object 형태로 파싱한다.

 

// 요청을 통해 얻은 JSON 타입의 Response 데이터 읽어오기
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line = "";
String result = "";

while((line = bufferedReader.readLine()) != null) {
    result += line;
}
System.out.println("response BODY : " + result);

// Gson 라이브러리에 포함된 클래스로 JSON 파싱 객체 생성
JsonParser jsonParser = new JsonParser();
JsonElement jsonElement = jsonParser.parse(result);

 

 

2-5.  Access Token, Refresh Token 꺼내기

2-4에서 만들어낸 object에서 access token을 꺼낸다.

이때, 사용한 bufferedReader, bufferedWriter는 close 해준다. 

 

access_Token = jsonElement.getAsJsonObject().get("access_token").getAsString();
refresh_Token = jsonElement.getAsJsonObject().get("refresh_token").getAsString();

System.out.println("access Token : " + access_Token);
System.out.println("refresh Token : " + refresh_Token);

bufferedReader.close();
bufferedWriter.close();

 

 

 

 

3. OAuthController에서 결과 확인

OAuthController에서 OAuthService 객체를 만들고 Run해서 결과를 확인해보자!

 

// OAuthController.java

package com.surveasy.surveasy.controller;

import com.surveasy.surveasy.service.OAuthService;
import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
public class OAuthController {
   
    private final OAuthService oAuthService;  // 이 부분 추가

    @ResponseBody
    @GetMapping("/kakao")
    public void kakaoCallBack(@RequestParam String code) {
        String access_Token = oAuthService.getKakaoAccessToken(code);
        System.out.println(access_Token);
    }
}

 

 

실행 결과, access token이 잘 리턴된 것을 확인할 수 있다 !