앱ID : 1038078
카카오 소셜 로그인 기능을 구현하고 있습니다.
카카오 로그인 페이지로 이동하여 로그인 정보 입력 > 동의항목 확인 후 동의하는 페이지까지는 정상적으로 뜨는 것을 확인했습니다.
동의하기 클릭 후 404 error로 페이지가 이동하고 있고,
인가 코드를 받은 후 토큰을 발급 받는 과정에서 오류가 발생하는 것으로 확인했습니다.
오류코드는 Response 401 UNAUTHORIZED 입니다.
관련 오류 로그
09:25:50,492 DEBUG [org.springframework.web.client.RestTemplate] (http-/0.0.0.0:18080-4) HTTP POST https://kauth.kakao.com/oauth/token
09:25:50,534 DEBUG [org.springframework.web.client.RestTemplate] (http-/0.0.0.0:18080-4) Accept=[application/json, application/*+json]
09:25:50,546 DEBUG [org.springframework.web.client.RestTemplate] (http-/0.0.0.0:18080-4) Writing [KakaoRequest [clientId=${정보보호}, redirectUri=http://localhost:18080/portal/login/oauth2/code/kakao.do, clientSecret=${정보보호}, responseType=null, scope=null, code=${정보보호}, accessType=null, grantType=authorization_code, state=null, includeGrantedScopes=null, loginHint=null, prompt=null]] with org.springframework.http.converter.json.MappingJackson2HttpMessageConverter
09:25:51,157 DEBUG [org.springframework.web.client.RestTemplate] (http-/0.0.0.0:18080-4) Response 401 UNAUTHORIZED
09:25:51,169 DEBUG [org.springframework.web.servlet.DispatcherServlet] (http-/0.0.0.0:18080-4) Failed to complete request: org.springframework.web.client.HttpClientErrorException$Unauthorized: 401 Unauthorized: [no body]
09:25:51,186 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/portal].[appServlet]] (http-/0.0.0.0:18080-4) JBWEB000236: Servlet.service() for servlet appServlet threw exception: org.springframework.web.client.HttpClientErrorException$Unauthorized: 401 Unauthorized: [no body]
at org.springframework.web.client.HttpClientErrorException.create(HttpClientErrorException.java:105) [spring-web-5.3.6.jar:5.3.6]
@RequestMapping(value = “/login/oauth2/code/kakao.do”)
public ModelAndView kakaoSocialLogin(@RequestParam(value = “code”) String authCode, HttpServletRequest request,
HttpServletResponse response, RedirectAttributes rs) throws Exception {
ModelAndView mnv = new ModelAndView();RestTemplate restTemplate = new RestTemplate(); KakaoRequest kakaoOAuthRequestParam = new KakaoRequest(); kakaoOAuthRequestParam.setClientId(getRegistrationVariable("kakao", "client-id")); kakaoOAuthRequestParam.setClientSecret(getRegistrationVariable("kakao", "client-secret")); kakaoOAuthRequestParam.setCode(authCode); kakaoOAuthRequestParam.setRedirectUri(getRegistrationVariable("kakao", "redirect-uri")); kakaoOAuthRequestParam.setGrantType("authorization_code"); ResponseEntity<KakaoResponse> resultEntity = restTemplate.postForEntity( getRegistrationVariable("kakao", "token-uri"), kakaoOAuthRequestParam, KakaoResponse.class);
String jwtToken = resultEntity.getBody().getId_token();
Map<String, String> idTokenRequest = new HashMap<>();
idTokenRequest.put(“id_token”, jwtToken);
ResponseEntity resultEntity2 = restTemplate
.postForEntity(“https://kauth.kakao.com/oauth/token”, idTokenRequest, KakaoInfResponse.class);SocialUser socialUser = resultEntity2.getBody().toSocialUser(); TokenProvider tokenProvider = new TokenProvider(); String oauthAccessToken = tokenProvider.generateOAuthAccessToken(response, jwtToken); Map<String, String> memberMap = new HashMap<>(); String id = socialUser.getId(); String userKey = crypt.getEncrypt(socialUser.getId()); String email = resultEntity2.getBody().getEmail(); memberMap.put("JOIN_TYPE", "K"); memberMap.put("EMAIL", email); memberMap.put("USER_KEY", userKey); List userInfoList = oAuth2Service.selectUserInfo(memberMap); if (userInfoList == null || userInfoList.isEmpty()) { CookieUtil.setCookie("SOCIAL_JOIN_TYPE", "K", request, response); CookieUtil.setCookie("EMAIL", email, request, response); CookieUtil.setCookie("ID", id, request, response); CookieUtil.setCookie("SOCIAL_USER_KEY", userKey, request, response); mnv.setViewName("redirect:/auth/joinAuth.do"); } else { Map<String, String> user = (Map) userInfoList.get(0); CookieUtil.setCookie("USER_KEY", user.get("USER_KEY"), request, response); mnv.setViewName("redirect:/auth/socialLoginProc.do"); } logger.info("20240220_kakao_login_test_end==========================="); return mnv;
}
…
- 설정된 properties정보
spring.security.oauth2.client.registration.kakao.redirect-uri=http://localhost:18080/portal/login/oauth2/code/kakao.do
spring.security.oauth2.client.registration.kakao.authorization-uri=카카오계정
spring.security.oauth2.client.registration.kakao.token-uri=https://kauth.kakao.com/oauth/token
디버그 해본 결과 오류가 발생하는 곳
ResponseEntity resultEntity = restTemplate.postForEntity(getRegistrationVariable(“kakao”, “token-uri”), kakaoOAuthRequestParam, KakaoResponse.class);
호출이 잘 안되고 있나해서 curl 명령어로 확인했습니다.
(code는 오류 로그에서 가져와서 확인했습니다.)
- 사용한 curl 명령어
$ curl -v -X POST https://kauth.kakao.com/oauth/token
-H “Content-Type: application/x-www-form-urlencoded”
-d ‘grant_type=authorization_code’
-d ‘code=${정보보호}’
-d ‘client_id=${정보보호}’
-d ‘client_secret=${정보보호}’
-d ‘redirect_uri=http://localhost:18080/portal/login/oauth2/code/kakao.do’
- 결과
Note: Unnecessary use of -X or --request, POST is already inferred.
- processing: https://kauth.kakao.com/oauth/token
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:–:-- --:–:-- --:–:-- 0* Trying 27.0.237.15:443…- Connected to kauth.kakao.com (27.0.237.15) port 443
- schannel: disabled automatic use of client certificate
- using HTTP/1.x
POST /oauth/token HTTP/1.1
Host: kauth.kakao.com
User-Agent: curl/8.2.1
Accept: /
Content-Type: application/x-www-form-urlencoded
Content-Length: 281} [281 bytes data]
- schannel: remote party requests renegotiation
- schannel: renegotiating SSL/TLS connection
- schannel: SSL/TLS connection renegotiated
- schannel: remote party requests renegotiation
- schannel: renegotiating SSL/TLS connection
- schannel: SSL/TLS connection renegotiated
< HTTP/1.1 200 OK
< Date: Thu, 22 Feb 2024 00:27:10 GMT
< Content-Type: application/json;charset=utf-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Cache-Control: no-cache, no-store, max-age=0, must-revalidate
< Pragma: no-cache
< Expires: 0
< X-XSS-Protection: 1; mode=block
< X-Frame-Options: DENY
< X-Content-Type-Options: nosniff
< Kakao: Talk
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Methods: GET, POST, OPTIONS
< Access-Control-Allow-Headers: Authorization, KA, Origin, X-Requested-With, Content-Type, Accept
<
{ [279 bytes data]
100 543 0 262 100 281 758 813 --:–:-- --:–:-- --:–:-- 1583{“access_token”:“${정보보호}”,“token_type”:“bearer”,“refresh_token”:“${정보보호}”,“expires_in”:21599,“scope”:“account_email”,“refresh_token_expires_in”:5183999}- Connection #0 to host kauth.kakao.com left intact
curl 명령어에서는 401이 아니라 HTTP/1.1 200 OK으로 확인했습니다.
client-id, client-secret, code는 문제가 없다고 생각되어 글을 올리게 됐습니다.
다른 분들의 게시글을 참고하여 시도한 방법
- header 정보 추가
@RequestMapping(value = “/login/oauth2/code/kakao.do”)
public ModelAndView kakaoSocialLogin(@RequestParam(value = “code”) String authCode, HttpServletRequest request,
HttpServletResponse response, RedirectAttributes rs) throws Exception {
logger.info(“20240220_kakao_login_test_start===========================”);ModelAndView mnv = new ModelAndView(); String credentials = getRegistrationVariable("kakao", "client-id") + ":" + getRegistrationVariable("kakao", "client-secret"); String base64Credentials = Base64.getEncoder().encodeToString(credentials.getBytes()); // header Setting HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED); headers.add("Authorization", "Basic " + base64Credentials); headers.add("Accept", "application/json"); RestTemplate restTemplate = new RestTemplate(); restTemplate.setMessageConverters(getMessageConverters()); MultiValueMap<String, String> params = new LinkedMultiValueMap<>(); params.add("grant_type", "authorization_code"); params.add("client_id", getRegistrationVariable("kakao", "client-id")); params.add("redirect_uri", getRegistrationVariable("kakao", "redirect-uri")); params.add("code", authCode); HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(params, headers);
오류 로그
10:05:38,183 DEBUG [org.springframework.web.client.RestTemplate] (http-/0.0.0.0:18080-2) Response 401 UNAUTHORIZED
10:05:40,845 DEBUG [org.springframework.web.servlet.DispatcherServlet] (http-/0.0.0.0:18080-2) Failed to complete request: org.springframework.web.client.HttpClientErrorException$Unauthorized: 401 Unauthorized: [no body]
10:05:40,855 ERROR [org.apache.catalina.core.ContainerBase.[jboss.web].[default-host].[/portal].[appServlet]] (http-/0.0.0.0:18080-2) JBWEB000236: Servlet.service() for servlet appServlet threw exception: org.springframework.web.client.HttpClientErrorException$Unauthorized: 401 Unauthorized: [no body]
- 오류 로그가 동일했습니다.
- IP 허용 주소 추가
- 오류 로그가 동일했습니다.