[Spring] Kakao Login

thingzoo·2023년 8월 9일
0

Spring

목록 보기
49/54
post-thumbnail

OAuth

OAuth는 인터넷 사용자들이 비밀번호를 제공하지 않고 다른 웹사이트 상의 자신들의 정보에 대해 웹사이트나 애플리케이션의 접근 권한을 부여할 수 있는 공통적인 수단으로서 사용되는, 접근 위임을 위한 개방형 표준이다.
사용자가 애플리케이션에게 모든 권한을 넘기지 않고 사용자 대신 서비스를 이용할 수 있게 해주는 HTTP 기반의 보안 프로토콜이다.
OAuth를 사용하는 서비스 제공자는 대표적으로 구글, 페이스북 등이 있다.
국내에는 대표적으로 네이버와 카카오가 있다.

이중에서 카카오 로그인을 공부해보자!

카카오 로그인 적용법

1. 카카오 로그인 승인 받기

아래는 카카오 로그인의 흐름이다.

  1. 일단 카카오 로그인을 사용하기 위해서는 카카오 개발 사이트에서 '애플리케이션 등록'이 필요하다.

  2. 내 애플리케이션 메뉴 > 애플리케이션 추가하기 클릭

  3. 앱 아이콘, 앱이름, 사업자명 저장

  4. 사이트 도메인 등록하기

  • 내 애플리케이션 > 앱 설정 > 플랫폼 클릭
  • web 플랫폼 등록 클릭후 도메인 입력
  1. 카카오로 로그인 했을 때 인가토큰을 받게 될 Redirect URI (callback) 를 설정하기
  • 등록하러 가기 클릭
  • 로그인에서 사용할 Redirect URI 입력
  • 활성화 설정
  1. 동의항목 설정
  • 카카오 로그인 > 동의항목 클릭
  • 닉네임 > 필수 동의
  • 필요시 이메일 > 선택동의

2. 카카오 사용자 정보 가져오기

참고
카카오 개발자 문서(카카오 로그인)

카카오 서버에서 인가코드 받기

  • 인가코드 요청 방법
    • 프론트 측에서 "카카오로 로그인" 버튼 클릭시 아래 주소로 이동하도록 구현
      https://kauth.kakao.com/oauth/authorize?client_id={REST_API_KEY}&redirect_uri={REDIRECT_URI}&response_type=code
    • REST API 키 확인
      • 앱 설정 > 앱키 > REST API 키

사용자가 카카오 로그인 페이지를 통해 '동의하고 계속하기'를 클릭하면, Redirect URI (callback)로 '인가코드'가 전달된다.

  • 카카오에서 보내주는 '인가코드' 처리 예시
    1. 카카오에서 보내주는 '인가코드'를 받음 ⇒ Controller
    2. '인가코드'를 가지고 카카오 로그인 처리 ⇒ Service
    3. 로그인 성공 시 "/" 으로 redirect ⇒ Controller

카카오 사용자 정보 가져오기

  1. "인가 코드"로 "액세스 토큰" 요청
private String getToken(String code) throws JsonProcessingException {
    // 요청 URL 만들기
    URI uri = UriComponentsBuilder
            .fromUriString("https://kauth.kakao.com")
            .path("/oauth/token")
            .encode()
            .build()
            .toUri();

    // HTTP Header 생성
    HttpHeaders headers = new HttpHeaders();
    headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");

    // HTTP Body 생성
    MultiValueMap<String, String> body = new LinkedMultiValueMap<>();
    body.add("grant_type", "authorization_code");
    body.add("client_id", "본인의 REST API키");
    body.add("redirect_uri", "http://localhost:8080/api/user/kakao/callback");
    body.add("code", code);

    RequestEntity<MultiValueMap<String, String>> requestEntity = RequestEntity
            .post(uri)
            .headers(headers)
            .body(body);

    // HTTP 요청 보내기
    ResponseEntity<String> response = restTemplate.exchange(
            requestEntity,
            String.class
    );

    // HTTP 응답 (JSON) -> 액세스 토큰 파싱
    JsonNode jsonNode = new ObjectMapper().readTree(response.getBody());
    return jsonNode.get("access_token").asText();
}
  1. "액세스 토큰"으로 "카카오 사용자 정보" 가져오기
private KakaoUserInfoDto getKakaoUserInfo(String accessToken) throws JsonProcessingException {
    // 요청 URL 만들기
    URI uri = UriComponentsBuilder
            .fromUriString("https://kapi.kakao.com")
            .path("/v2/user/me")
            .encode()
            .build()
            .toUri();

    // HTTP Header 생성
    HttpHeaders headers = new HttpHeaders();
    headers.add("Authorization", "Bearer " + accessToken);
    headers.add("Content-type", "application/x-www-form-urlencoded;charset=utf-8");

    RequestEntity<MultiValueMap<String, String>> requestEntity = RequestEntity
            .post(uri)
            .headers(headers)
            .body(new LinkedMultiValueMap<>());

    // HTTP 요청 보내기
    ResponseEntity<String> response = restTemplate.exchange(
            requestEntity,
            String.class
    );

    JsonNode jsonNode = new ObjectMapper().readTree(response.getBody());
    Long id = jsonNode.get("id").asLong();
    String nickname = jsonNode.get("properties")
            .get("nickname").asText();
    String email = jsonNode.get("kakao_account")
            .get("email").asText();

    log.info("카카오 사용자 정보: " + id + ", " + nickname + ", " + email);
    return new KakaoUserInfoDto(id, nickname, email);
}
profile
공부한 내용은 바로바로 기록하자!

0개의 댓글