STEP 3 사용자 로그인 처리
https://developers.kakao.com/docs/latest/ko/kakaologin/rest-api#req-user-info
React
STEP 2에서 발급받은 토큰을 서버로 보내는 코드를 작성한다.
export const getJwtToken = async (accessToken) => {
const jwtToken = fetch(`http://localhost:8080/members/signup/kakao?accessToken=${accessToken}`)
.then(res => res.json())
.catch((err) => console.log(err));
}
리다이렉트 페이지에 다음 코드를 추가한다.
인가 코드를 받아서 authCode가 변경되면 토큰을 요청하고 토큰을 받으면 서버(Spring Boot)측으로 토큰을 전달하고 Jwt 토큰을 받는다.
import { useEffect } from "react";
import { useSearchParams } from "react-router-dom";
import { getAccessToken, getJwtToken } from "../api/kakaoApi";
const KakaoRedirectPage = () => {
const [searchParams] = useSearchParams();
const authCode = searchParams.get("code");
useEffect(() => {
getAccessToken(authCode).then((data) => getJwtToken(data.access_token));
}, [authCode]);
return (
<div>
<p>Kakao Login Reditect</p>
<p>${authCode}</p>
</div>
);
};
export default KakaoRedirectPage;
Spring Boot
프런트엔드(React)에서 보낸 토큰을 받기 위한 Controller를 만든다.
@RestController
@RequestMapping("/members")
class MemberController (
private val memberService: MemberService
){
@GetMapping("/signup/kakao")
fun signupKakao(accessToken: String): ResponseEntity<MutableMap<String, Any>> {
return ResponseEntity.status(HttpStatus.CREATED).body(memberService.getMemberInfoFormKakao(accessToken))
}
}
Controller를 통해 받은 토큰으로 카카오 서버에서 사용자 정보를 가져오기 위해 Service를 만든다.
@Service
class MemberService(
private val memberRepository: MemberRepository
) {
private val log = LoggerFactory.getLogger(this::class.java)
fun getMemberInfoFormKakao(accessToken: String): MutableMap<String, Any> {
// 토큰 값이 null인 경우, 카카오 서버측에서는 우리가 클라이언트이기 때문에 400을 우리에게 던짐
// 그러면 우리의 클라이언트 쪽에는 500에러가 전달되므로 여기서 예외를 잡아서 프런트 쪽으로 전달해야 함
if (accessToken == "undefined") {
throw IllegalArgumentException("Access token cannot be empty")
}
val getMemberInfoURL = "https://kapi.kakao.com/v2/user/me"
val restTemplate = RestTemplate()
val headers = HttpHeaders()
headers.add("Authorization", "Bearer $accessToken")
headers.add("Content-Type", "application/x-www-form-urlencoded;charset=utf-8")
val entity = HttpEntity<String>(headers)
val responseBody = restTemplate.exchange(getMemberInfoURL, HttpMethod.GET, entity, Map::class.java).body
val kakaoAccount = responseBody?.get("kakao_account") as Map<*, *>
val email = kakaoAccount["email"]
val profile = kakaoAccount["profile"] as Map<*, *>
val nickname = profile["nickname"]
val profileImageUrl = profile["profile_image_url"]
log.info("********** email: {}", email)
log.info("********** nickname: {}", nickname)
log.info("********** profileImageUrl: {}", profileImageUrl)
// 회원가입 처리
}
}
'TIL(Today I Learned)' 카테고리의 다른 글
TIL - React에서 useState를 사용할 때 호출이 여러 번 발생 (0) | 2024.06.05 |
---|---|
Spring AOP(Aspect-Oriented Programming) (1) | 2024.06.04 |
TIL - Redis Key값에 특수 문자(이상한 문자)가 같이 들어가는 경우 (0) | 2024.05.31 |
TIL - React, Spring Boot로 카카오 소셜 로그인 구현 STEP 2 (0) | 2024.05.30 |
TIL - Redis: java.net.UnknownHostException (0) | 2024.05.30 |