728x90

 


 

OAuth는 크게 3단계로 나뉘어 있다.

  1. 서비스를 등록하는 과정
    • 원하는 소셜 로그인 회사에 본인 웹 애플리케이션 등록하기
    • 이 과정에서 redirect_uri 등을 합의하기
  2. 토큰을 받기 위한 과정
    • 사용자를 소셜로그인 페이지로 이동시키기
    • 소셜 로그인 회사가 사용자를 우리 서비스로 Redirect 시키기
  3. 토큰을 이용해 사용자 정보를 요청하는 과정

 

 

OAuth의 이론적인 부분에 대한 내용은 다음 포스팅에 작성해 놓았다.

https://jminie.tistory.com/128

 

OAuth 개념 및 동작 방식

우리는 자주 어느 사이트에 로그인을 하려고 하면 외부 소셜 계정을 기반으로 간편히 로그인할 수 있는 웹 애플리케이션을 쉽게 찾아볼 수 있다. 예를 들어, 외부 웹 애플리케이션에 카카오로

jminie.tistory.com

 

 

 


 

 

 

 

📌  서비스를 등록하는 과정

우선 Kakao developers에서 우리가 구현하고자 하는 앱을 등록해야 한다.

이 내용은 Kakao developers 공식문서에 자세히 나와있으니 링크를 참고하여 등록하도록 하자.

https://developers.kakao.com/docs/latest/ko/kakaologin/prerequisite

 

Kakao Developers

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

developers.kakao.com

 

 

 

 

 

 

📌  토큰을 받기 위한 과정

 

카카오 로그인이 진행되는 과정을 간략히 표현하면 다음과 같다.

 

 

 

 

 

📝   인가 코드 받기

인가 코드 받기는 카카오 로그인을 시작하는 단계로써, 카카오 로그인 동의 화면을 호출하고, 사용자 동의를 거쳐 인가 코드 발급을 요청하는 API이다.

 

 

사용자는 동의 화면에서 서비스 이용 시 필요한 사용자 정보 및 권한 제공에 동의하고 로그인을 요청하게 된다.

사용자가 필수 동의 항목에 모두 동의한 뒤 [동의하고 계속하기] 버튼을 누르면, 카카오 인증 서버는 해당 사용자에 대한 인가 코드를 발급해 내가 카카오에 등록한 redirect_uri에 전달하게 된다.

 

 

 

 

 

🔑  토큰 받기

인가 코드를 받은 뒤, 인가 코드로 액세스 토큰과 리프레시 토큰을 발급받는 API이다. 인가 코드를 받는 것 만으로는 카카오 로그인에 성공하지 못한다. 토큰 받기까지 마쳐야 카카오 로그인을 정상적으로 완료할 수 있다.

 

 

우선 필수 파라미터 값들을 담아 POST로 요청한다.

요청 성공 시, 응답은 Redirect URI에 전달되며 두 가지 종류의 토큰 값(Access Token, Refresh Token)과 타입, 초 단위로 된 만료 시간을 포함한 JSON 객체로 오게 된다.

 

예시

 

 

 

사용자가 로그인에 성공하면 발급되는 액세스 토큰(Access Token)과 리프레시 토큰(Refresh Token)은 각각 역할과 유효기간이 다르다. 실제 사용자 인증을 맡는 액세스 토큰은 비교적 짧은 만료 시간을 가진다.

하지만 유효한 리프레시 토큰이 있다면, 사용자가 다시 로그인했을 때 리프레시 토큰으로 액세스 토큰을 다시 발급받을 수 있다.

 

 

 

 

 

이 프로젝트에서는 인가 코드 받기와 토큰 받기가 Provider(Service) 단에서 처리하도록 구현했다.

 

UserProvider.java

    public KakaoOAuthToken getKakaoOAuthToken(String code){
        try{
            RestTemplate restTemplate = new RestTemplate();

            //HttpHeader 오브젝트 생성
            HttpHeaders headers = new HttpHeaders();
            headers.add("Content-type","application/x-www-form-urlencoded;charset=utf-8");

            //HttpBody 오브젝트 생성
            MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
            params.add("grant_type","authorization_code");
            params.add("client_id","5ecd5893f1f093aae717200483bce75d");
            params.add("redirect_uri","http://localhost:9000/app/users/auth/kakao/callback");
            params.add("code",code);

            //HttpHeader와 HttpBody를 하나의 오브젝트에 담기
            HttpEntity<MultiValueMap<String,String>> kakaoTokenRequest = new HttpEntity<>(params, headers);

            //Http 요청하기 (POST 방식으로)
            ResponseEntity<String> response = restTemplate.exchange(
                    "https://kauth.kakao.com/oauth/token",
                    HttpMethod.POST,
                    kakaoTokenRequest,
                    String.class
            );

            ObjectMapper objectMapper = new ObjectMapper();

            KakaoOAuthToken oauthTokenKakao = objectMapper.readValue(response.getBody(), KakaoOAuthToken.class);

            return oauthTokenKakao;
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return null;
        }
    }

 

 

Reqest

Header

  • Content-type : application/x-www-form-urlencoded;charset=utf-8 로 고정

 

Body

  • grant_type : authorization_code로 고정
  • client_id : 앱 REST API 키(처음 카카오 로그인에 내 앱을 등록할 때 설정되는 앱 키이다. [내 애플리케이션] > [앱 키]에서 확인 가능하다.)
  • redirect_uri : 인가 코드가 리다이렉트된 URI (처음 내 앱을 등록할 때 설정한 redirect_uri)
  • code : 인가 코드 받기 요청으로 얻은 인가 코드 (로그인을 요청할 때마다 인가 코드가 달라지므로 code라는 동적인 객체 에로 만들어준다.) 

 

 

이렇게 설정해주고

HTTP Header와 body를 하나의 오브젝트 kakaoTokenRequest에 담아서 

POST방식으로 "https://kauth.kakao.com/oauth/token" 에 HTTP 요청을 보낸다.

 

 

이제 redirect_uri에 콜백으로 온 Response JSON객체를 ObjectMapper를 이용해 KakaoOAuthToken 객체로 받아와서 return 해준다.

 

 

KakaoOAuthToken.java

import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
public class KakaoOAuthToken {
    private String access_token;
    private String token_type;
    private String refresh_token;
    private int expires_in;
    private String scope;
    private int refresh_token_expires_in;
}

 

 

위 KakaoOAuthToken.java를 살펴보면 위에서 말한 것처럼 두 가지 종류의 토큰 값(Access Token, Refresh Token)과 타입, 초 단위로 된 만료 시간이 들어있는 것을 확인할 수 있다.

 

 

 

 

 

 

 

📌  토큰을 이용해 사용자 정보를 요청하는 과정

현재 로그인한 사용자의 정보를 불러온다. 사용자 정보 요청 REST API는 사용자 액세스 토큰을 사용하는 방법, 앱 어드민 키를 사용하는 방법 두 가지로 제공되는데 이 프로젝트에서는 액세스 토큰을 사용하는 방법으로 구현하였다.

 

 

HTTP 헤더에 엑세스 토큰을 담아 POST방식으로 "https://kapi.kakao.com/v2/user/me"로 요청한다.

 

 

사용자 정보 요청 성공 시, 응답 바디(Body)는 JSON 객체로 사용자 정보를 포함하여 오게 된다.

 

UserProvider.java

 public KakaoProfile getKakaoProfile(String accessToken){

        RestTemplate rt = new RestTemplate();
        //HttpHeader 오브젝트 생성
        HttpHeaders headers2 = new HttpHeaders();
        headers2.add("Authorization", "Bearer "+accessToken);
        headers2.add("Content-type","application/x-www-form-urlencoded;charset=utf-8");

        // HttpHeader와 HttpBody를 하나의 오브젝트에 담기
        HttpEntity<MultiValueMap<String,String>> kakaoProfileRequest = new HttpEntity<>(headers2);

        //  Http 요청하기 - Post방식으로 - 그리고 response 변수의 응답 받음
        ResponseEntity<String> response2 = rt.exchange(
                "https://kapi.kakao.com/v2/user/me",
                HttpMethod.POST,
                kakaoProfileRequest,
                String.class
        );

        ObjectMapper objectMapper = new ObjectMapper();
        KakaoProfile kakaoProfile = null;
        try {
            kakaoProfile = objectMapper.readValue(response2.getBody(),KakaoProfile.class);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
        }

        return kakaoProfile;
    }

 

 

 

Request

Header

  • Authorization: Bearer {ACCESS_TOKEN}
  • Content-type: application/x-www-form-urlencoded;charset=utf-8로 고정

 

이렇게 설정해주고

HTTP Header와 body를 하나의 오브젝트 kakaoProfileRequest에 담아서 

POST방식으로 "https://kapi.kakao.com/v2/user/me"에 HTTP 요청을 보낸다.

 

 

 

이제 로그인한 사용자의 정보(로그인할 때 동의한 항목에 한해서)가 kakaoProfile에 담기게 된다. 

 

 

KakaoProfile.java

import lombok.Data;


@Data
public class KakaoProfile {

    public int id;
    public String connected_at;
    public Properties properties;
    public KakaoAccount kakao_account;

    @Data
    public class Properties {

        public String nickname;
        public String profile_image;
        public String thumbnail_image;

    }

    @Data
    public class KakaoAccount {

        public Boolean profile_nickname_needs_agreement;
        public Boolean profile_image_needs_agreement;
        public Profile profile;
        public Boolean has_email;
        public Boolean email_needs_agreement;
        public Boolean is_email_valid;
        public Boolean is_email_verified;
        public String email;

        @Data
        public class Profile {

            public String nickname;
            public String thumbnail_image_url;
            public String profile_image_url;
            public Boolean is_default_image;
        }
    }
}

 

 

 

이렇게 

 

  1. 서비스를 등록하는 과정
    • 원하는 소셜 로그인 회사에 본인 웹 애플리케이션 등록하기
    • 이 과정에서 redirect_uri 등을 합의하기
  2. 토큰을 받기 위한 과정
    • 사용자를 소셜로그인 페이지로 이동시키기
    • 소셜로그인 회사가 사용자를 우리 서비스로 Redirect 시키기
  3. 토큰을 이용해 정보를 요청하는 과정

 

을 구현해 보았다. 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

Reference:

https://developers.kakao.com/docs/latest/ko/kakaologin/prerequisite

 

복사했습니다!