OAuth 정의
OAuth는 인터넷 사용자들이 비밀번호를 제공하지 않고 다른 웹사이트 상의 자신들의 정보에 대해 웹사이트나 애플리케이션의 접근 권한을 부여할 수 있는 공통적인 수단으로서 사용되는, 접근 위임을 위한 개방형 표준이다.
Plain Text
복사
REST API를 이용하는 카카오 로그인 과정
KakaoController.java
프론트를 고려하지 않은 코드
@Controller
@RequiredArgsConstructor
public class KakaoController {
    private final KakaoService kakaoService;
    @GetMapping("/kakao-login")
    public String homepage() {
        return "kakao";
    }
    @GetMapping("${kakao.redirect-uri}")
    public String kakaoLogin(@RequestParam String code, HttpServletResponse response)
            throws JsonProcessingException {
        kakaoService.kakaoLogin(code, response);
        return "redirect:/kakao-login";
    }
}
JavaScript
복사
문제점이 무엇일까요?
프론트를 고려한 코드
@Controller
@RequiredArgsConstructor
public class KakaoController {
    private final KakaoService kakaoService;
    @ResponseBody
    @GetMapping("/api/${mpt.version}/users/kakao-code")
    public RedirectView redirectView() {
        String url = kakaoService.redirect();
        return new RedirectView(url);
    }
    @GetMapping("/api/${mpt.version}/users/kakao-login")
    public void kakaoLogin(@RequestParam String code, HttpServletResponse response)
            throws JsonProcessingException {
        kakaoService.kakaoLogin(code, response);
    }
}
JavaScript
복사
KakaoService.java
1.
인가 코드 받기
a.
public String redirect() {
        return "https://kauth.kakao.com/oauth/authorize?response_type=code&client_id="
                + CLIENT_ID
                + "&redirect_uri="
                + TARGET_IP
                + REDIRECT_URI;
    }
JavaScript
복사
2.
토큰 받기
a.
private String getToken(String code) throws JsonProcessingException {
        String TOKEN_URI = "https://kauth.kakao.com/oauth/token";
        String GRANT_TYPE = "?grant_type=authorization_code";
        RestClient restClient = RestClient.create();
        String response =
                restClient
                        .post()
                        .uri(
                                TOKEN_URI
                                        + GRANT_TYPE
                                        + "&client_id="
                                        + CLIENT_ID
                                        + "&redirect_uri="
                                        + TARGET_IP
                                        + REDIRECT_URI
                                        + "&code="
                                        + code
                                        + "&client_secret="
                                        + SECRET_KEY)
                        .header("Content-type", "application/x-www-form-urlencoded;charset=utf-8")
                        .retrieve()
                        .body(String.class);
        JsonNode jsonNode = new ObjectMapper().readTree(response);
        return jsonNode.get("access_token").asText();
    }
JavaScript
복사
3.
사용자 정보 가져오기
a.
private UserSignUpReq getKaKaoUserInfo(String accessToken) throws JsonProcessingException {
        String INFO_URI = "https://kapi.kakao.com/v2/user/me";
        RestClient restClient = RestClient.create();
        String response =
                restClient
                        .get()
                        .uri(INFO_URI)
                        .header("Authorization", "Bearer " + accessToken)
                        .header("Content-type", "application/x-www-form-urlencoded;charset=utf-8")
                        .retrieve()
                        .body(String.class);
        JsonNode jsonNode = new ObjectMapper().readTree(response);
        String nickname = jsonNode.get("properties").get("nickname").asText();
        String email = jsonNode.get("kakao_account").get("email").asText();
        return UserSignUpReq.builder()
                .email(email)
                .password(UUID.randomUUID().toString())
                .username(nickname)
                .build();
    }
JavaScript
복사
4.
응답 헤더에 jwt 토큰 보내기
a.
public void kakaoLogin(String code, HttpServletResponse response)
            throws JsonProcessingException {
        String accessToken = getToken(code);
        UserSignUpReq req = getKaKaoUserInfo(accessToken);
        UserEntity userEntity =
                UserEntity.builder()
                        .email(req.email())
                        .username(req.username())
                        .password(req.password())
                        .build();
        if (userRepository.findByEmail(req.email()).isEmpty()) {
            userRepository.save(userEntity);
        }
        String token = jwtUtil.createToken(userEntity.getEmail());
        log.info(token);
        response.addHeader(TOKEN_HEADER, token);
    }
JavaScript
복사



