Skip to content

Commit

Permalink
Merge pull request #58 from taco-official/KL-155/kakao-oauth-2-구현
Browse files Browse the repository at this point in the history
feat(KL-155): create kakao oauth2
  • Loading branch information
ohhamma authored Aug 23, 2024
2 parents 07c7ec5 + 4f851dd commit 2fdb4c7
Show file tree
Hide file tree
Showing 21 changed files with 516 additions and 14 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package taco.klkl.domain.oauth.controller;

import java.net.URI;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;

import com.fasterxml.jackson.core.JsonProcessingException;

import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import taco.klkl.domain.oauth.service.OauthKakaoService;
import taco.klkl.domain.user.dto.response.UserDetailResponse;

@Slf4j
@RestController
@RequestMapping("/v1/oauth/kakao")
@RequiredArgsConstructor
@Tag(name = "9. 인증/인가", description = "인증/인가 API")
public class OauthKakaoController {

private final OauthKakaoService oauthKakaoService;

@Value("${spring.security.oauth2.client.registration.kakao.client-id}")
private String clientId;

@Value("${spring.security.oauth2.client.provider.kakao.authorization-uri}")
private String authorizationUri;

@Value("${spring.security.oauth2.client.registration.kakao.redirect-uri}")
private String redirectUri;

@Value("${api.main-url}")
private String mainUrl;

/**
* 클라이언트를 Kakao Oauth URL로 리다이렉트합니다.
* @return
*/
@GetMapping()
@Operation(summary = "kakao 간편로그인 요청", description = "카카오 oauth를 사용하여 로그인 처리합니다.")
public ResponseEntity<Void> oauthKakao() {
final String location = getKakaoOauthLocation();
final URI locationUri = URI.create(location);

return ResponseEntity
.status(HttpStatus.FOUND)
.location(locationUri)
.build();
}

/**
* Kakao 리다이렉트 받은 code값으로 사용자 로그인처리를 합니다.
* @param code
* @return
* @throws JsonProcessingException
*/
// TODO: JWT적용시 토큰 관리 로직 추가
@GetMapping("/code")
@Operation(summary = "kakao 사용자 정보 가져오기", description = "카카오 API를 사용하여 사용자 정보를 가져옵니다.")
public UserDetailResponse processKakaoOauth2(@RequestParam("code") final String code) throws
JsonProcessingException {

return oauthKakaoService.kakaoOauthLogin(code);
}

/**
* Kakao Oauth 요청 URL을 구성합니다.
* @return
*/
private String getKakaoOauthLocation() {
StringBuilder location = new StringBuilder();
location.append(authorizationUri)
.append("?response_type=").append("code")
.append("&client_id=").append(clientId)
.append("&redirect_uri=").append(mainUrl).append(redirectUri);

return location.toString();
}

}
11 changes: 11 additions & 0 deletions src/main/java/taco/klkl/domain/oauth/dao/OauthRepository.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package taco.klkl.domain.oauth.dao;

import org.springframework.data.jpa.repository.JpaRepository;

import taco.klkl.domain.oauth.domain.Oauth;

public interface OauthRepository extends JpaRepository<Oauth, Long> {
boolean existsByOauthMemberId(final Long oauthMemberId);

Oauth findFirstByOauthMemberId(final Long oauthMemberId);
}
42 changes: 42 additions & 0 deletions src/main/java/taco/klkl/domain/oauth/domain/Oauth.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package taco.klkl.domain.oauth.domain;

import jakarta.persistence.Column;
import jakarta.persistence.Entity;
import jakarta.persistence.FetchType;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import jakarta.persistence.OneToOne;
import lombok.AccessLevel;
import lombok.Getter;
import lombok.NoArgsConstructor;
import taco.klkl.domain.user.domain.User;

@Getter
@Entity(name = "oauth")
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Oauth {

@Id
@Column(name = "oauth_id")
@GeneratedValue(strategy = GenerationType.AUTO)
Long id;

@OneToOne(optional = false, fetch = FetchType.EAGER)
private User user;

@Column(
name = "oauth_member_id",
nullable = false
)
private Long oauthMemberId;

private Oauth(final User user, final Long oauthMemberId) {
this.user = user;
this.oauthMemberId = oauthMemberId;
}

public static Oauth of(final User user, final Long oauth2MemberId) {
return new Oauth(user, oauth2MemberId);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package taco.klkl.domain.oauth.dto.request;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public record KakaoUserInfoRequest(Long oauthMemberId, String nickname, String profileImage) {

public static KakaoUserInfoRequest of(final Long oauthMemberId, final String nickname, final String profileImage) {
return new KakaoUserInfoRequest(oauthMemberId, nickname, profileImage);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package taco.klkl.domain.oauth.service;

import org.springframework.stereotype.Service;

import taco.klkl.domain.oauth.dto.request.KakaoUserInfoRequest;
import taco.klkl.domain.user.dto.response.UserDetailResponse;

@Service
public interface OauthKakaoLoginService {
UserDetailResponse loginUser(final KakaoUserInfoRequest userInfoRequest);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package taco.klkl.domain.oauth.service;

import org.springframework.context.annotation.Primary;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import taco.klkl.domain.oauth.dao.OauthRepository;
import taco.klkl.domain.oauth.domain.Oauth;
import taco.klkl.domain.oauth.dto.request.KakaoUserInfoRequest;
import taco.klkl.domain.user.domain.Gender;
import taco.klkl.domain.user.domain.User;
import taco.klkl.domain.user.dto.request.UserCreateRequest;
import taco.klkl.domain.user.dto.response.UserDetailResponse;
import taco.klkl.domain.user.service.UserService;
import taco.klkl.global.util.UserUtil;

@Slf4j
@Primary
@Service
@Transactional
@RequiredArgsConstructor
public class OauthKakaoLoginServiceImpl implements OauthKakaoLoginService {

private final OauthRepository oauthRepository;
private final UserService userService;
private final UserUtil userUtil;

/**
* Oauth의 결과로 사용자 로그인 처리를 수행합니다.
* TODO: 현재 더미유저 데이터로 인해 최초요청은 에러발생
* @param userInfoRequest
* @return
*/
public UserDetailResponse loginUser(final KakaoUserInfoRequest userInfoRequest) {

final Long oauthMemberId = userInfoRequest.oauthMemberId();

// 이미 oauth로그인 기록이 있는 유저를 처리합니다.
if (oauthRepository.existsByOauthMemberId(oauthMemberId)) {
final Oauth oauth = oauthRepository.findFirstByOauthMemberId(oauthMemberId);
final User user = oauth.getUser();
return UserDetailResponse.from(user);
}

final User user = registerUser(userInfoRequest);
final Oauth oauth = Oauth.of(user, userInfoRequest.oauthMemberId());
oauthRepository.save(oauth);

return UserDetailResponse.from(user);
}

private User registerUser(final KakaoUserInfoRequest userInfoRequest) {

final String name = userUtil.createUsername(userInfoRequest.nickname(), userInfoRequest.oauthMemberId());

// TODO: 성별, 나이는 기본값으로 넣고 있습니다.
final UserCreateRequest userCreateRequest = UserCreateRequest.of(
name,
Gender.MALE.getDescription(),
0,
userInfoRequest.profileImage(),
""
);

// 유저를 DB에 생성합니다.
return userService.createUser(userCreateRequest);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package taco.klkl.domain.oauth.service;

import org.springframework.stereotype.Service;

import com.fasterxml.jackson.core.JsonProcessingException;

import taco.klkl.domain.user.dto.response.UserDetailResponse;

@Service
public interface OauthKakaoService {
UserDetailResponse kakaoOauthLogin(final String code) throws JsonProcessingException;
}
Loading

0 comments on commit 2fdb4c7

Please sign in to comment.