카카오 로그인 OAuth2.0 - 사용자 정보 조회
지난 포스팅에서는 인가 코드 그랜트 유형 방식으로 카카오 OAuth 2 로그인 인증을 진행했다. 카카오 개발자 사이트에 앱을 등록 후, 나의 웹브라우저에서 카카오 코드(태그)를 요청하고, 나의 서버로 응답받는 작업까지 진행을 했다.
이번 포스팅에서는 엑세스토큰을 요청하고, 받은 엑세스 토큰으로 나의 카카오 사용자 정보를 얻는 방법을 살펴본다.
3단계 - 코드(태그)로 엑세스 토큰 교환
지금은 상황에서 코드(태그)는 클라이언트 화면이 가지고 있고, 서버 세션에도 등록되어 있다. 우리는 클라이언트에서 코드를 넘겨 받을것이므로 컨트롤러에 코드 파라미터를 받아주는 로직을 작성해준다. 그 다음 Spring restTemplate 객체를 이용해서 카카오 엑세스 토큰을 받기 위한 파라미터들을 HTTP BODY에 넣어준다. 여기서 파라미터 키인 grant_type, client_id, redirect_uri, code는 모두 카카오 개발자 사이트에 정의되어 있다. 모두 필수 값이다. 여기서 중요한 점은 client_id를 Rest API key로 작성해 주어야 한다는 점이다. 그리고 code는 클라이언트에서 파라미터로 넘겨 받은 code를 넣어준다. restTemplate 객체로 post 요청을 한후 응답값을 클라이언트로 넘겨 준다.
//카카오 나의 엑세스 토큰 요청하기.
@RequestMapping(value = "/selectMyAccessTockenWithKakao", method = RequestMethod.GET)
@ResponseBody
public String selectMyAccessTockenWithKakao(@RequestParam String code , Model model , HttpServletRequest request) throws JsonProcessingException {
System.out.println("selectMyAccessTockenWithKakao 진입!--");
//클라이언트에서 받은 코드
System.out.println("code : " + code);
MultiValueMap<String, String> parameters = new LinkedMultiValueMap<>();
parameters.add("grant_type", "authorization_code");
parameters.add("client_id", "d345f48c50cbd61611c496d9708d72b2"); //rest api key
parameters.add("redirect_uri", "http://localhost:8080/oauth"); //redirect 주소는 등록한 주소로....
parameters.add("code", code);
String url = "https://kauth.kakao.com/oauth/token";
KakaoTokenVO body = null;
try {
ResponseEntity<KakaoTokenVO> enti = restTemplate.postForEntity(url, parameters, KakaoTokenVO.class);
body = enti.getBody();
String tokenType = body.getToken_type();
String refreshToken = body.getRefresh_token();
String accessTocken = body.getAccess_token();
String expiresTime = body.getExpires_in();
String refreshExpiresTime = body.getRefresh_token_expires_in();
System.out.println("토큰 타입 : " + tokenType);
System.out.println("리프레쉬 토큰 : " + refreshToken);
System.out.println("엑세스 토큰 : " + accessTocken);
System.out.println("만료기간 : " + expiresTime);
System.out.println("리프레쉬 토큰 만료기간 : " + refreshExpiresTime);
} catch (HttpStatusCodeException e) {
System.out.println("error :" + e);
}
ObjectMapper mapper = new ObjectMapper();
String result = mapper.writeValueAsString(body);
return result;
}
엑세스토큰 요청 화면
카카오 엑세스 토큰을 요청하기 위한 화면은 아래와 같다. 지난 포스팅에서 작성한 내용 모두 적어 주었다. 카카오에서 받은 코드를 ajax 를 이용해서 get 방식으로 위에서 만든 클라이언트로 전달하는 코드이다. 주석으로 나의 토큰 가져오기 부분을 확인하자.
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page contentType="text/html; charset=UTF-8" language="java"%>
<html>
<head>
<title>카카오 로그인</title>
<script src="https://developers.kakao.com/sdk/js/kakao.js"></script>
<script>
// SDK를 초기화 합니다. 사용할 앱의 JavaScript 키를 설정해 주세요.
Kakao.init('070e574cef4ec45be518f989611aff42');
// SDK 초기화 여부를 판단합니다.
console.log(Kakao.isInitialized());
</script>
</head>
<body>
<h1>Hello world!</h1>
<a id="custom-login-btn" href="javascript:loginWithKakao()">
<img
src="//k.kakaocdn.net/14/dn/btqCn0WEmI3/nijroPfbpCa4at5EIsjyf0/o.jpg"
width="222"
/>
</a>
<br>
<%
String code = null;
session = request.getSession();
if(session.getAttribute("code") != null){
code = (String)session.getAttribute("code");
out.print("<h5>code: " + code + "</h5>" + "<br>");
%>
<input type="hidden" id="code" value=<%=code%> />
<a id="mytoken" href="javascript:selectMyAccessTockenWithKakao()">나의 토큰 정보 얻기</a>
<%
}else{
out.print("*로그인 후 code를 받으세요." +"<br>");
}
%>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
var code = null;
if(document.getElementById("code") != null){
//코드 체크
var code = document.getElementById("code").value;
if(code != null){
//코드 존재
console.log("code 존재");
console.log(code);
Kakao.Auth.setAccessToken(code);
}else{
console.log("code 없음");
}
}
//카카오 로그인
function loginWithKakao() {
Kakao.Auth.authorize({
redirectUri: 'http://localhost:8080/oauth'
});
}
//나의 토큰 가져오기
function selectMyAccessTockenWithKakao() {
var param = {"code" : code}
$.ajax({
url : '/selectMyAccessTockenWithKakao',
type : 'get',
data : param,
dataType : "JSON",
contentType: "application/x-www-form-urlencoded;charset=utf-8",
success : function(data){
console.log(data);
},
error: function(xhr, type){
console.log(xhr);
console.log(type);
}
})
}
엑세스토큰 요청 하기
아래 사진 처럼 카카오 계정으로 로그인 한 후 아래 나의 토큰 정보 얻기 버튼을 클릭하면 우측에 access_token이 카카오 서버로부터 나의 서버를 거쳐서 클라이언트 사이드까지 응답된 것을 알 수가 있다. 이 엑세스 토큰이 있어야지 카카오 사용자 정보, 카카오 친구 등 카카오 정보를 요청 할 수가 있다.
PostMan으로 엑세스 토큰 요청 테스트
위 테스트에서 오류가 발생했거나, 잘 작동이 안된다면 포스트 맨을 열어서 아래와 같이 테스트 할 수 있다. 요청 URL 주소를 확인하고, 파라미터 4개의 이름을 확인하자. 그리고 카카오 개발자 사이트에 등록된 정보가 맞는지 마지막으로 확인해보자. 참고로 Body 부분에 요청파라미터를 넣어야 한다. Headers에 넣어준건 아닌지도 확인해 보자.
4단계 - 엑세스토큰으로 나의 정보 얻기
엑세스 토큰까지 얻었으니 이 토큰으로 사용자 정보를 요청해 보는 로직을 작성해 보자. 먼저 컨트롤러 부터 작성한다. 나의 정보 얻기 컨트롤러 내용은 아래와 같다. 엑세스 토큰을 @RequestParam 어노테이션을 사용해서 받아왔다. 그리고 중요한점은 이번엔 엑세스 토큰을 HTTP Headers에 파라미터로 넣어준다는 것이다. 절대로 Body에 넣어서 요청하면 안된다. 오류난다. 우리는 계속 스프링 restTemplate으로 진행을 해왔기때문에 restTemplate으로 요청할때 Headers에 값을 넣어주기위해서 HttpHeaders 객체를 만들었다. 이 객체에 아래 처럼 값을 넣고, Authorization 키에는 Bearer + 엑세스 토큰 값을 넣어야 한다는 것을 주의하자.
//카카오 나의 정보 얻기
@RequestMapping(value = "/selectMyInfoWithKakao", method = RequestMethod.GET, produces="application/json;charset=utf-8")
@ResponseBody
public String selectMyInfoWithKakao(@RequestParam String tocken) {
String myTocken = "Bearer " + tocken;
//헤더 객체 생성
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
headers.set("Authorization", myTocken);
//요청 url
UriComponentsBuilder builder =
UriComponentsBuilder.fromHttpUrl("https://kapi.kakao.com/v2/user/me");
HttpEntity<?> entity = new HttpEntity<>(headers);
HttpEntity<String> response = null;
//요청
try {
response = restTemplate.exchange(
builder.toUriString(),
HttpMethod.GET,
entity,
String.class);
System.out.println("응답결과 :" + response.getBody());
} catch (HttpStatusCodeException e) {
System.out.println("error :" + e);
}
return response.getBody();
}
나의 정보 가져오기 화면 작성
마지막으로 카카오 서비스에서 나의 정보를 가져오기 위해서는 엑세스 토큰까지 준비가 되어 있어야 한다. 이 로직에서는 null 체크 하는 부분은 전혀 없다. 그래서 최종적으로 나의 정보를 얻어올려면, 카카오계정로그인 -> 코드 발급 확인 -> 나의 정보 얻기 순으로 버튼을 클릭해야 한다. 화면 로직은 전체 로직을 다 넣었다. 얻은 엑세스 토큰으로 위에서 만들어준 컨트롤러를 호출해주는게 전부다. 주석으로 나의 정보 가져오기 부분을 참고하면 된다.
<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ page contentType="text/html; charset=UTF-8" language="java"%>
<html>
<head>
<title>카카오 로그인</title>
<script src="https://developers.kakao.com/sdk/js/kakao.js"></script>
<script>
// SDK를 초기화 합니다. 사용할 앱의 JavaScript 키를 설정해 주세요.
Kakao.init('070e574cef4ec45be518f989611aff42');
// SDK 초기화 여부를 판단합니다.
console.log(Kakao.isInitialized());
</script>
</head>
<body>
<h1>
Hello world!
</h1>
<a id="custom-login-btn" href="javascript:loginWithKakao()">
<img
src="//k.kakaocdn.net/14/dn/btqCn0WEmI3/nijroPfbpCa4at5EIsjyf0/o.jpg"
width="222"
/>
</a>
<br>
<%
String code = null;
session = request.getSession();
if(session.getAttribute("code") != null){
code = (String)session.getAttribute("code");
out.print("<h5>code: " + code + "</h5>" + "<br>");
%>
<input type="hidden" id="code" value=<%=code%> />
<input type="hidden" id="tocken" value="" />
<a id="mytoken" href="javascript:selectMyAccessTockenWithKakao()">나의 토큰 정보 얻기</a>
<a id="myinfo" href="javascript:selectMyInfoWithKakao()">나의 정보 얻기</a>
<%
}else{
out.print("*로그인 후 code를 받으세요." +"<br>");
}
%>
<script src="http://code.jquery.com/jquery-latest.min.js"></script>
<script type="text/javascript">
var code = null;
if(document.getElementById("code") != null){
//코드 체크
var code = document.getElementById("code").value;
if(code != null){
//코드 존재
console.log("code 존재");
console.log(code);
Kakao.Auth.setAccessToken(code);
}else{
console.log("code 없음");
}
}
//카카오 로그인
function loginWithKakao() {
Kakao.Auth.authorize({
redirectUri: 'http://localhost:8080/oauth'
});
}
//나의 토큰 가져오기
function selectMyAccessTockenWithKakao() {
var param = {"code" : code}
$.ajax({
url : '/selectMyAccessTockenWithKakao',
type : 'get',
data : param,
dataType : "JSON",
contentType: "application/x-www-form-urlencoded;charset=utf-8",
success : function(data){
console.log(data);
console.log(data['access_token']); //토큰얻기
document.getElementById("tocken").value = data['access_token']; //토큰 할당
},
error: function(xhr, type){
console.log(xhr);
console.log(type);
}
})
}
//나의 정보 가져오기
function selectMyInfoWithKakao() {
var myTocken = document.getElementById("tocken").value
var param = {"tocken" : myTocken}
$.ajax({
url : '/selectMyInfoWithKakao',
type : 'get',
data : param,
dataType : "JSON",
contentType: "application/x-www-form-urlencoded;charset=utf-8",
success : function(data){
console.log(data);
},
error: function(xhr, type){
console.log(xhr);
console.log(type);
}
})
}
</script>
</body>
</html>
나의 정보 얻기 테스트
서버를 재시작 한후에 아래 화면에서 로그인하기 버튼 클릭, 나의 토큰 정보 얻기 버튼 클릭 후 마지막으로 나의 정보 얻기 태그를 클릭하자.
PostMan으로 테스트
포스트맨으로도 카카오 나의정보 요청 테스트가 가능하다.
참고
REST API는 크로스도메인 요청을 허용하고 있지 않기 때문에 ajax로 직접 요청을 할 수 없다.
아래 2가지 방법 중 한 가지 방법을 선택해서 사용하실 수 있다.
1) REST API를 사용하고 Server to Server로 요청
2) javascript sdk 사용
정리
이번 포스팅에서는 카카오 서비스에서 받은 코드(태그) 값을 이용해서 엑세스 토큰을 얻고, 엑세스 토큰을 이용해서 나의 카카오 정보를 얻는 방법을 살펴 보았다. 개념을 모르는 상태에서 구현하는 것 보다, OAuth2 인증에 대한 개념을 이해한 상태에서 구현을 하는것이 더 도움이 될것같다.
✅스프링 RestTemplate으로 HTTP Get 방식 요청하기
예제코드
'웹개발 > 보안' 카테고리의 다른 글
jwt 토큰 - java로 생성하기 예제 (0) | 2021.03.08 |
---|---|
JWT - JSON Web Token 이란 - 개념 (0) | 2021.03.05 |
카카오 로그인 OAuth2.0 (0) | 2020.12.08 |
OAuth2 인증 - 인가 코드 그랜트 (0) | 2020.12.05 |
OAuth2 인증 - 암시적 코드 그랜트 (0) | 2020.12.05 |