spring boot REST API Web 프로젝트 (12 - 2) - OAuth 2.0 카카오 로그인 part.1 Authorization code + Token 발급

2021. 8. 29. 13:27·스프링/스프링부트 RestAPI 프로젝트

스프링 부트 REST API WEB 프로젝트

깃헙 링크

https://github.com/choiwoonsik/springboot_RestApi_App_Project/tree/main/restApiSpringBootApp

수행 목록

  1. 환경구성 및 helloworld 출력
  2. H2 DB 연동
  3. Swagger API 문서 연동
  4. REST API 설계
  5. RestControllerAdvice를 이용한 통합 예외 처리
  6. Entity - DTO 분리
  7. MessageSource를 이용해 예외 메시지 다국화
  8. JPA Aduting을 이용해 객체 생성시간/수정시간 적용
  9. 스프링 시큐리티 + Jwt를 이용해서 인증 및 권한 체크
  10. 스프링 시큐리티 AuthenticationEntryPoint, AccessDenied로 인증 및 인가 예외처리
  11. Jwt AccessToken + RefreshToken으로 보안성과 사용자 편의성 고도화하기
  12. JUnit Test (단위 테스트)
  13. JUnit Test (통합 테스트)
  14. OAuth 2.0 정리
  15. OAuth 2.0 카카오 로그인 part.1 Authorization code + Token 발급
  16. OAuth 2.0 카카오 로그인 part.2 토큰으로 회원 가입 / 로그인
  17. OAuth 2.0 카카오 로그인 테스트 검증
  18. 환경별 설정을 위해서profile 분리하기 

앞에서 정리한 OAuth 2.0을 바탕으로 직접 구현해본다

  • 정리글 : OAuth 2.0 정리

카카오 OAuth 로직

위와 같은 로직으로 카카오 로그인이 돌아간다.

 

카카오 로그인 사용을 위한 작업

  1. 카카오 Developers 사이트에 가서 자신의 APP을 생성
    • https://developers.kakao.com/console/app/627892/config/platform
  2. 로그인 페이지 / 콜백 페이지 연동
  3. AccessToken을 통해 가입 및 로그인

 

1. 카카오 Developers 설정

웹 앱의 주소 등록 : 앱설정 -> 플랫폼

콜백 주소 (Redirect URI) 등록 : 카카오 로그인


2.  로그인 페이지 / 콜백 페이지 구현

카카오와 통신이 필요하므로 RestTemplate를 빈으로 등록

@Bean
public RestTemplate getRestTemplate() {
	return new RestTemplate();
}

 

카카오 연동 결과 Json을 객체로 매핑하기 위해 Gson 라이브러리를 사용. 의존성 추가

// Json을 결과로 매핑하기 위한 의존성
implementation 'com.google.code.gson:gson'

 

2- 1. 카카오 api와 연동하기 위한 설정정보 application.yml 작성

  • https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api
  • 카카오 API 내용은 공식 사이트에 잘 정리되어있으니 참고해서 작성하면 된다.

인가코드받기

GET /oauth/authorize?client_id={REST_API_KEY}&redirect_uri={REDIRECT_URI}&response_type=code HTTP/1.1
Host: kauth.kakao.com
https://kauth.kakao.com/oauth/authorize?response_type=code&client_id={REST_API_KEY}&redirect_uri={REDIRECT_URI}

토큰받기

POST /oauth/token HTTP/1.1
Host: kauth.kakao.com
Content-type: application/x-www-form-urlencoded;charset=utf-8

사용자정보 가져오기

GET/POST /v2/user/me HTTP/1.1
Host: kapi.kakao.com
Authorization: Bearer {ACCESS_TOKEN}
Content-type: application/x-www-form-urlencoded;charset=utf-8

사용자 연결 끊기 (재동의를 위해 구현)

POST /v1/user/unlink HTTP/1.1
Host: kapi.kakao.com
Authorization: Bearer {ACCESS_TOKEN}

 

위 내용을 가지고 application.yml을 작성

social:
  kakao:
    client-id: {REST_API_PRIVATE_KEY}
    redirect: /oauth/kakao/redirect
    url:
      login: https://kauth.kakao.com/oauth/authorize
      token: https://kauth.kakao.com/oauth/token
      profile: https://kapi.kakao.com/v2/user/me
      unlink: https://kapi.kakao.com/v1/user/unlink
url:
  base: http://localhost:8080
  1. [http://localhost:8080/oauth/kakao/login]로 접속
  2. 카카오 로그인 버튼이 있는 창을 띄어줌, 해당 버튼을 누르면 요청 URL을 보내고 카카오 로그인 창이 뜨게 된다.
  3. 요청 URL은 [인가 코드 받기]에 있는 URL이다.
  • 요청 URL 형식 : https://kauth.kakao.com/oauth/authorize?response_type=code&client_id={REST_API_KEY}&redirect_uri={REDIRECT_URI}

 

2- 2.  카카오 인가 코드 받기

카카오 서버에 나의 {REST_API_KEY} 와 {REDIRECT_URI}를 담아서 GET 요청
    @Value("${url.base}")
    private String baseUrl;

    @Value("${social.kakao.client-id}")
    private String kakaoClientId;

    @Value("${social.kakao.redirect}")
    private String kakaoRedirectUri;

    @GetMapping("/login")
    public ModelAndView socialLogin(ModelAndView mav) {

        StringBuilder loginUri = new StringBuilder()
                .append(env.getProperty("social.kakao.url.login"))
                .append("?response_type=code")
                .append("&client_id=").append(kakaoClientId)
                .append("&redirect_uri=").append(baseUrl).append(kakaoRedirectUri);
        mav.addObject("loginUrl", loginUri);
        mav.setViewName("social/login");
        return mav;
    }

 

카카오톡 로그인 버튼을 갖는 view 만듬 : resources/templates/social/login.ftl
<button onclick="popupKakaoLogin()">KakaoLogin</button>
<script>
    function popupKakaoLogin() {
        window.open('${loginUrl}', 'popupKakaoLogin', 'width=700,height=500,scrollbars=0,toolbar=0,menubar=no')
    }
</script>
  • 사용자가 카카오 로그인 버튼을 누르면
  • -> 위에서 작성한 loginUri로 요청이 가고 카카오톡 로그인 창이 뜸
  • -> 사용자는 로그인 후 동의항목을 체크하고 진행
  • -> 이때 URL은 client_id와 redirect_uri를 가지고 있고, 카톡 서버가 검증 후 redirect_uri로 사용자의 Authorization_code (인가 코드)를 쿼리 파라미터로 포함해서 리다이렉트 한다. (이때 카카오는 카카오의 회원정보를 나의 앱과 연동시킨다.)

카카오 로그인 시 redirect_uri, client_id가 포함되어 있다.

카카오가 돌려준 AuthorizationCode를 가지고 토큰 받기

redirect_uri는 내가 미리 카톡 API 서버에 지정해둔 것이므로 해당 리다이렉트 주소에 맞게 처리하면 된다.

    @GetMapping(value = "/redirect")
    public ModelAndView redirectKakao(
            ModelAndView mav,
            @ApiParam(value = "Authorization Code", required = true)
            @RequestParam String code) {

        mav.addObject("authInfo", kakaoService.getKakaoTokenInfo(code));
        mav.setViewName("social/redirectKakao");
        return mav;
    }

쿼리 파라미터에서 [인가 코드]를 얻어서 카카오에게 토큰을 요청한다.

  • kakaoService.getKakaoTokenInfo(code) 메소드를 작성하자

 

2-3. 카카오 토큰

  • [grant_type, 인가 코드, client_id, redirect_uri] 를 포함해서 카카오에 POST 요청해주면 카카오가 토큰을 돌려준다.
  • 해당 토큰을 매핑하기 위한 RetKakaoOAuth객체를 만든다.
RetKakaoOAuth 객체
package com.restApi.restApiSpringBootApp.dto.social;

@Getter
public class RetKakaoOAuth {
    private String token_type;
    private String access_token;
    private Integer expires_in;
    private String refresh_token;
    private String refresh_token_expires_in;
    private String scope;
}

❗️이때 gson을 이용하기위해 객체의 프로퍼티는 json의 key-value의 key이름과 동일하게 작성한다❗️

 

2.4 전달받은 [인가코드]로 [Token] 발급받기

  • [grant_type, 인가 코드, client_id, redirect_uri]를 담아서 POST 요청을 보낸다.
  • 정상적인 경우 Token을 전달받을 수 있다. 토큰 값을 RetKakaoOAuth객체로 매핑한다.

 

카카오 토큰 데이터를 RestKakaoToken으로 매핑
    public RetKakaoOAuth getKakaoTokenInfo(String code) {
        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);

        MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
        params.add("grant_type", "authorization_code");
        params.add("client_id", kakaoClientId);
        params.add("redirect_uri", baseUrl + kakaoRedirectUri);
        params.add("code", code);

        String requestUri = env.getProperty("social.kakao.url.token");
        if (requestUri == null) throw new CCommunicationException();

        HttpEntity<MultiValueMap<String, String>> request = new HttpEntity<>(params, headers);
        ResponseEntity<String> response = restTemplate.postForEntity(requestUri, request, String.class);

        if (response.getStatusCode() == HttpStatus.OK)
            return gson.fromJson(response.getBody(), RetKakaoOAuth.class);
        throw new CCommunicationException();
    }

응답이 제대로 왔다면

  • gson을 이용해서 전달받은 Json 데이터를 ReKakaoOAuth로 매핑한다.
  • 이때 gson을 이용하려면 객체의 프로퍼티는 json의 key-value의 key이름과 동일해야한다.

 

발급받은 토큰 확인을 위한 view : resources/templates/social/redirectKakao.ftl
<ol>
    <li>token_type : ${authInfo.token_type}</li>
    <li>access_token : ${authInfo.access_token}</li>
    <li>expires_in : ${authInfo.expires_in}</li>
    <li>refresh_token : ${authInfo.refresh_token}</li>
    <li>refresh_token_expires_in : ${authInfo.refresh_token_expires_in}</li>
    <li>scope : ${authInfo.scope}</li>
</ol>

 

결과적으로 유저는 카카오 로그인을 통해 카카오로부터 Token을 발급 받았다. 이제 이 토큰을 이용해서 카카오에게 유저 정보를 요청하고 해당 유저 정보가 유효하다면, 그 정보를 이용해서 회원가입 시키면 된다.
-
내용이 길어져서 끊고 바로 다음 장에서 이어서 진행
반응형
저작자표시 (새창열림)

'스프링 > 스프링부트 RestAPI 프로젝트' 카테고리의 다른 글

spring boot REST API Web 프로젝트 (12 - 4) - OAuth 2.0 카카오 로그인 테스트 검증  (1) 2021.09.02
spring boot REST API Web 프로젝트 (12 - 3) - OAuth 2.0 카카오 로그인 part.2 토큰으로 회원 가입 / 로그인  (0) 2021.08.31
spring boot REST API Web 프로젝트 (12 - 1) - OAuth 2.0 정리  (0) 2021.08.26
spring boot REST API Web 프로젝트 (11 - 2) - JUnit Test (통합 테스트)  (0) 2021.08.24
spring boot REST API Web 프로젝트 (11 - 1) - JUnit Test (단위 테스트)  (0) 2021.08.23
'스프링/스프링부트 RestAPI 프로젝트' 카테고리의 다른 글
  • spring boot REST API Web 프로젝트 (12 - 4) - OAuth 2.0 카카오 로그인 테스트 검증
  • spring boot REST API Web 프로젝트 (12 - 3) - OAuth 2.0 카카오 로그인 part.2 토큰으로 회원 가입 / 로그인
  • spring boot REST API Web 프로젝트 (12 - 1) - OAuth 2.0 정리
  • spring boot REST API Web 프로젝트 (11 - 2) - JUnit Test (통합 테스트)
구름뭉치
구름뭉치
구름의 개발일기장
  • 구름뭉치
    구름 개발일기장
    구름뭉치
  • 전체
    오늘
    어제
    • ALL (283)
      • 프로젝트 (23)
        • 토스페이먼츠 PG 연동 시리즈 (12)
        • JWT 방식 인증&인가 시리즈 (6)
        • 스우미 웹 애플리케이션 프로젝트 (1)
        • 스프링부트 기본 보일러 플레이트 구축 시리즈 (2)
        • 마이크로서비스 아키텍쳐 시리즈 (1)
      • 스프링 (43)
        • 스프링부트 API 설계 정리 (8)
        • 스프링부트 RestAPI 프로젝트 (18)
        • 스프링부트 WebSocket 적용기 (3)
        • 스프링 JPA 정리 시리즈 (5)
        • 스프링 MVC (5)
        • 스프링 배치 (2)
        • 토비의 스프링 정리 (2)
      • 기술 학습 (28)
        • 아파치 카프카 (9)
        • 클린 코드 (4)
        • 디자인 패턴의 아름다움 (2)
        • 모던 자바 인 액션 (7)
        • JVM 스레드 딥다이브 (6)
      • Web (25)
        • 정리글 (20)
        • GraphQL 정리글 (2)
        • Jenkins 정리글 (3)
      • 취업 (6)
      • CS (77)
        • 네트워크 전공 수업 정리 (11)
        • OSI 7계층 정리 (12)
        • 운영체제 정리 (19)
        • 데이터베이스 정리 (5)
        • MySql 정리 (17)
        • GoF의 Design Pattern 정리 (12)
      • 알고리즘 (70)
        • 백준 (56)
        • 프로그래머스 (12)
        • 알고리즘 정리본 (1)
      • 기초 지식 정리 (2)
      • 일상 (8)
  • 블로그 메뉴

    • 홈
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    류블라냐
    크로아티아
    동유럽
    마우스
    mx master s3 for mac
    마우스 패드
    레이저
    부다페스트
    키보드 손목 받침대
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.6
구름뭉치
spring boot REST API Web 프로젝트 (12 - 2) - OAuth 2.0 카카오 로그인 part.1 Authorization code + Token 발급
상단으로

티스토리툴바