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
복사