Spring boot + React + Kakao Login 연동하기
Kakao Developers에 도메인 주소 : 프론트 http://localhost:3000으로 설정되어 있어야함
- 프론트 서버에서 http://localhost:3000 접속 후 카카오 로그인 하면 인가 code를 받아 access token을 발급 받고 백엔드로 전달
- 전달 받은 access token을 가지고 카카오로부터 사용자 정보 받아와 우리 DB에 저장 ( ID: 카카오 이메일, PW: 임의 문자열 )
- 우리 DB에 저장된 사용자 정보를 가지고 JWT 토큰 생성 후 프론트로 전달
- 프론트에서 localStorage에 JWT 토큰 저장
- 추후 API 사용시 헤더에 JWT 토큰 포함해 요청
# Kakao Developers 설정
- 앱 도메인 프론트엔드 주소로 설정 http://localhost:3000
- Redirect URI 설정 http://localhost:8080/auth/kakao/callback
- 카카오 로그인 활성화 On
# 프론트엔드 설정
1 JavaScript SDK 적용 및 초기화
public/index.html
<!DOCTYPE html>
<html lang="en">
<head>
:
<script src="https://developers.kakao.com/sdk/js/kakao.js"></script>
<script>Kakao.init('JAVASCRIPT_KEY');</script>
<title>Therapist</title>
</head>
<body>
<main id="root"></main>
<div id="modal"></div>
</body>
</html>
Kakao Developers에 등록한 앱의 JAVA SCRIPT 키를 이용하여 SDK 초기화
https://developers.kakao.com/docs/latest/ko/getting-started/sdk-js
Kakao Developers
카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.
developers.kakao.com
2 리액트 컴포넌트에서 Kakao API 요청으로 카카오 로그인 처리
- 브라우저의 window 객체에서 Kakao API 가져오기 const { kakao } = window;
- 리액트 컴포넌트 상단에 아래 코드를 작성하여 Kakao api 에 접근할 수 있다.
- Kakao.Auth.login 함수를 사용하여 카카오 로그인 팝업창 출력 및 로그인 처리
- 클릭 이벤트 핸들러에서 Kakao.Auth.login 함수를 호출하면 카카오 로그인 동의화면 띄울 수 있으며, 동의화면을 통해 사용자로부터 사용자 정보 및 기능 활용 동의를 받을 수 있다.
- 인가된 사용자일 경우 success 콜백함수를 사용해 카카오 사용자 토큰을 받아옴
- 로그인 성공 후 fetch 함수를 이용해 카카오에서 보내준 카카오 사용자 토큰 access_token 을 백엔드 서버로 보냄 (카카오앱에 등록해둔 Redirect URI)
- 백엔드단에서 access_token을 가지고 카카오로 사용자 정보를 요청 후 받아와 MariaDB에 저장하고 JWT 토큰 만들어 프론트단으로 반환
- 받아온 JWT 토큰을 프론트단에서 localStorage에 저장
- 마지막으로 history.push 함수를 사용해서 이동시키고자 웹 페이지로 보내준다.
import React, { useState } from 'react';
import { withRouter, Link } from 'react-router-dom';
import ModalPortal from '../../../../portal/ModalPortal.js';
import { useHistory } from "react-router-dom";
import './RightMenu.css';
const { kakao } = window;
function RightMenu() {
const history = useHistory();
const kakaoLoginClickHandler = () => {
Kakao.Auth.login({
success: function (authObj) {
fetch(`${"http://localhost:8080/auth/kakao/callback?accessToken="+authObj.access_token}`, {
method: "GET",
})
.then(res => res.json())
.then(res => {
localStorage.setItem("token", res.token);
if (res.access_token) {
alert("welcome")
history.push("/");
}
})
},
fail: function (err) {
alert(JSON.stringify(err))
}
})
};
return (
<Button fill className="btn kakao" onClick={kakaoLoginClickHandler}>카카오 로그인</Button>
);
};
export default RightMenu;
[React] 카카오 소셜 로그인
이번 프로젝트에서 카카오 소셜 로그인을 맡게 되었다. 소셜 로그인 중 카카오가 가장 쉽다고 한다. 그 이유는 카카오 개발자 사이트에서 사용 가이드를 친절하게 작성해놓았기 때문이라고 한
velog.io
https://developers.kakao.com/docs/latest/ko/kakaologin/js
Kakao Developers
카카오 API를 활용하여 다양한 어플리케이션을 개발해보세요. 카카오 로그인, 메시지 보내기, 친구 API, 인공지능 API 등을 제공합니다.
developers.kakao.com
# 백엔드 설정
1 받아온 Access token으로 사용자 처리 / 생성한 JWT토큰 반환
AuthController
- 받아온 토큰을 requestKakaoUserInfo 함수로 보내 카카오 사용자 정보를 처리하여 userMap에 담는다.
- ID : kakao_email
- PW : 랜덤 문자열
- userMap으로 받아온 사용자 정보로 UserDto생성하여 /account/register API 요청으로 우리 DB에 저장
- 이 때 password Encoding 하여 DB에 저장
- JWT토큰을 생성하기 위해 username과 password를 LoginDto에 담아 해당 API로 보냄
- 반환받은 JWT토큰({"token": "ey ~~"} <type: String>)을 JSONObject에 담아 프론트로 전달
@CrossOrigin("*")
@GetMapping("/kakao/callback")
public JSONObject kakaoCallback(String accessToken) throws ParseException { // @ResponseBody : Data를 리턴해주는 컨트롤러 함수
Map<String, String> userMap = userService.requestKakaoUserInfo(accessToken);
System.out.println("accessToken: "+accessToken);
RestTemplate rt = new RestTemplate();
// builder 이용하여 UserDto 필드 초기화
UserDto newUser = UserDto.builder()
.userName(userMap.get("username"))
.userPassword(userMap.get("password"))
.userProfileImage(userMap.get("profile_image"))
.userThumbnailImage(userMap.get("thumbnail_image"))
.userEnabled(true)
.build();
HttpEntity<UserDto> requestEntity = new HttpEntity<>(newUser);
rt.exchange(
"http://localhost:8080/account/register",
HttpMethod.PUT,
requestEntity,
Void.class
);
LoginDto loginDto = LoginDto.builder()
.username(userMap.get("username"))
.password(userMap.get("password"))
.build();
String response = userService.requestPostWithFormData("/auth/authenticate", loginDto);
JSONParser parser = new JSONParser();
Object token = parser.parse(response);
JSONObject res = (JSONObject) token;
return res;
}
※ 나만 겪은 issue..
여기서 굉장히 헤맸는데, 처음에 제대로 다 했는데도 자꾸 KEO 320 에러가 났다
아니 나는 계속 새롭게 카카오 로그인을 누르는데 어째서 두 번 이상 사용하게 된건가 했더니
https://devtalk.kakao.com/t/topic/109348/4
코드 받고 토큰 요청 시 오류 발생
카카오 데브톡. 카카오 플랫폼 서비스 관련 질문 및 답변을 올리는 개발자 커뮤니티 사이트입니다.
devtalk.kakao.com
이 글을 보고 다시 코드를 보니 애초에 프론트에서 인가 code를 받아 백으로 보내주는게 access token인데 나는 받아오는게 인가코드인줄 알고 access token으로 access token을 또 받아오려고 했던것..ㅋㅋ 삽질은 언제나 이상한데서ㅠ
// 변경 전
public ResponseEntity<String> kakaoCallback(String code) { // @ResponseBody : Data를 리턴해주는 컨트롤러 함수
String accessToken = userService.getAccessToken(code);
Map<String, String> userMap = userService.requestKakaoUserInfo(accessToken);
// 변경 후
public JSONObject kakaoCallback(String accessToken) throws ParseException { // @ResponseBody : Data를 리턴해주는 컨트롤러 함수
// 프론트에서 Kakao 서버로 인증코드 받아 인증된 사용자면 access token을 보내옴
Map<String, String> userMap = userService.requestKakaoUserInfo(accessToken);
+ CORS 이슈
public class WebConfig implements WebMvcConfigurer {
@Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("*");
}
}