기초설정은 https://velog.io/@joonoo3/Oauth2로-소셜로그인-기초-원리-카카오 이곳에서 참고해주세요!
이전 포스트에서 올렸던 자료인데 기초 설정만으로 얼마나 해주는지 살펴보겠습니다.
스프링부트를 실행해주고
http://localhost:8080/oauth2/authorization/kakao 에 접속해봅니다.
이와 같이 https://kauth.kakao.com/oauth/authorize?~ 주소로 리다이렉트 되는것을 확인할 수 있습니다.
개발자 도구에서도 확인할 수 있습니다!
이제 동의를 누르면 카카오 서버에서는 미리 설정해둔 리다이렉트 url인
http://localhost:8080/oauth2/kakao~ 로 인가코드를 보내줄겁니다!
그럼 저희도 /oauth2/kakao를 받아 매핑할 controller를 만들어줘야겠죠?
카카오 디벨로퍼스 https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#request-code-sample 에 있는 내용입니다. code값으로 param을 받아와야 하겠네요!
@GetMapping("/oauth2/kakao")
public String kakaoCode(@RequestParam("code") String code) {
return code;
}
다시 로그인 해주면
이제 카카오에 정상적으로 로그인 했다는 인가코드를 받았으니 사용자 정보를 알아오기 위한 토큰을 받아오겠습니다!
https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#request-token-request 에 있는 내용을 보면
여러 값을 param으로 건네주어야 함을 알 수 있습니다.
그래서 컨트롤러에 변수를 선언하고 Value로 값을 주입해주고 WebFlux설정을 해줍니다.
Value 어노테이션 사용법 : https://velog.io/@joonoo3/Spring-BootAnnotation-Value
@RestController
@RequestMapping
@RequiredArgsConstructor
@Slf4j
public class AuthController {
@Value("${spring.security.oauth2.client.registration.kakao.client-id}")
private String clientId;
@Value("${spring.security.oauth2.client.registration.kakao.client-secret}")
private String clientSecret;
@Value("${spring.security.oauth2.client.registration.kakao.redirect-uri}")
private String redirectUri;
@GetMapping("/oauth2/kakao")
public Oauth2TokenDTO kakaoLogin(@RequestParam("code") String code) {
String targetUrl = "https://kauth.kakao.com/oauth/token?grant_type=authorization_code&client_id="
+ clientId + "&redirect_uri=" + redirectUri + "&code=" + code + "&client_secret=" + clientSecret;
WebClient webClient = WebClient.builder()
.baseUrl(targetUrl)
.build();
log.info("targetUrl : {}", targetUrl);
Oauth2TokenDTO json = webClient
.post()
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.retrieve()
.bodyToMono(Oauth2TokenDTO.class)
.block();
return json;
}
}
참고로 Oauth2TokenDTO는 https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#request-token-response 에 있는 반환값을 토대로 작성한 클래스 입니다.
밑 코드를 참고하세요!
@Builder
@Getter
@RequiredArgsConstructor
@AllArgsConstructor
public class Oauth2TokenDTO {
private String access_token;
private String refresh_token;
private String token_type;
private Long expires_in;
private String scope;
private String refresh_token_expires_in;
}
이제 다시로그인 해주면
토큰이 잘 넘어옴을 확인 할 수 있습니다!
사실 여기까지 하면 사용자 정보는 위와 같이 WebClient로 카카오에서 제공하는 API로 요청을
보내면 받을 수 있습니다.
이 후 포스팅에서 Oauth2 라이브러리를 사용하여 훨씬 더 쉽게 유저 정보를 받아올 수 있어서 이 부분은 raw 코드로 더 완성시키고 싶은 분에게 추천합니다.
먼저, 카카오 디벨로퍼 https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#req-user-info에서 제공하는 유저정보 API 엔드포인트는 https://kapi.kakao.com/v2/user/me 입니다.
헤더는 엑세스 토큰을 요구하고 있으니 WebClient을 두번 써야 하겠네요.
코드가 길어질 것 같으니 메서드를 추출하겠습니다.
@GetMapping("/oauth2/kakao")
public KakaoUserInfoDTO kakaoLogin(@RequestParam("code") String code) {
Oauth2TokenDTO json = getOauth2TokenDTO(code);
KakaoUserInfoDTO authorization = getKakaoUserInfoDTO(json);
return authorization;
}
//유저 정보 받아오기
private KakaoUserInfoDTO getKakaoUserInfoDTO(Oauth2TokenDTO json) {
String UserInfoUrl = "https://kapi.kakao.com/v2/user/me";
WebClient webClient2 = WebClient.builder()
.baseUrl(UserInfoUrl)
.build();
KakaoUserInfoDTO userInfo = webClient2.post()
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.headers(httpHeaders ->
httpHeaders.add("Authorization", "Bearer " + json.getAccess_token())
).retrieve().bodyToMono(KakaoUserInfoDTO.class)
.block();
return userInfo;
}
//토큰 얻어오기
private Oauth2TokenDTO getOauth2TokenDTO(String code) {
String targetUrl = "https://kauth.kakao.com/oauth/token?grant_type=authorization_code&client_id="
+ clientId + "&redirect_uri=" + redirectUri + "&code=" + code + "&client_secret=" + clientSecret;
WebClient webClient = WebClient.builder()
.baseUrl(targetUrl)
.build();
log.info("targetUrl : {}", targetUrl);
Oauth2TokenDTO token = webClient
.post()
.contentType(MediaType.APPLICATION_FORM_URLENCODED)
.retrieve()
.bodyToMono(Oauth2TokenDTO.class)
.block();
return token;
}
참고로 KakaoUserInfoDTO 는 파싱하기 쉽게 만든 객체입니다!
@Builder
@Getter
@AllArgsConstructor
@NoArgsConstructor
public class KakaoUserInfoDTO {
private Long id;
private Boolean has_signed_up;
private String connected_at;
private String synched_at;
private String properties;
private KakaoAccount kakao_account;
private String for_partner;
@Builder
@Getter
@AllArgsConstructor
@NoArgsConstructor
public static class KakaoAccount{
private Boolean profile_nickname_needs_agreement;
private Boolean profile_image_needs_agreement;
private Boolean has_email;
private Boolean email_needs_agreement;
private Boolean is_email_valid;
private Boolean is_email_verified;
private String email;
}
}
다시 로그인 해보면
잘 반환 되었네요!
다음 포스팅에서는 기존 코드를 모두 자동화해주는 Oauth 라이브러리를 사용해보겠습니다!