Skip to content

Commit

Permalink
✨ feat: KAKAO OAuth 사용자 가입 로직 구현 (#42)
Browse files Browse the repository at this point in the history
  • Loading branch information
loveysuby committed Sep 4, 2024
1 parent 9abd27e commit 830f849
Show file tree
Hide file tree
Showing 5 changed files with 173 additions and 1 deletion.
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package slvtwn.khu.toyouserver.application.auth;

import static slvtwn.khu.toyouserver.common.response.ResponseType.NOT_SUPPORTED_AUTH_PROVIDER;

import jakarta.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
import slvtwn.khu.toyouserver.application.auth.strategy.KakaoAuthStrategy;
import slvtwn.khu.toyouserver.application.auth.strategy.SocialAuthStrategy;
import slvtwn.khu.toyouserver.domain.SocialAuthProvider;
import slvtwn.khu.toyouserver.dto.SocialAuthRequest;
import slvtwn.khu.toyouserver.dto.SocialAuthResponse;
import slvtwn.khu.toyouserver.exception.ToyouException;

@Component
@RequiredArgsConstructor
public class SocialAuthContext {

private KakaoAuthStrategy kakaoAuthStrategy;

private final List<SocialAuthStrategy> socialAuthStrategies = new ArrayList<>();

@PostConstruct
void initSocialLoginContext() {
socialAuthStrategies.add(kakaoAuthStrategy);
}

public boolean support(SocialAuthProvider provider) {
for (SocialAuthStrategy strategy : socialAuthStrategies) {
if (strategy.support(provider.toString())) {
return true;
}
}
return false;
}

public SocialAuthResponse doLogin(final SocialAuthRequest request) {
for (SocialAuthStrategy strategy : socialAuthStrategies) {
if (strategy.support(request.provider().toString())) {
return strategy.login(request);
}
}
throw new ToyouException(NOT_SUPPORTED_AUTH_PROVIDER);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package slvtwn.khu.toyouserver.application.auth.strategy;

import static slvtwn.khu.toyouserver.domain.SocialAuthProvider.KAKAO;

import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import slvtwn.khu.toyouserver.application.AuthService;
import slvtwn.khu.toyouserver.common.feign.auth.kakao.KakaoAuthApiClient;
import slvtwn.khu.toyouserver.common.feign.auth.kakao.KakaoResourceApiClient;
import slvtwn.khu.toyouserver.common.feign.auth.kakao.web.KakaoTokenResponse;
import slvtwn.khu.toyouserver.common.feign.auth.kakao.web.KakaoUserResponse;
import slvtwn.khu.toyouserver.domain.User;
import slvtwn.khu.toyouserver.domain.UserOAuthCredential;
import slvtwn.khu.toyouserver.domain.UserOAuthCredentialRepository;
import slvtwn.khu.toyouserver.dto.SocialAuthRequest;
import slvtwn.khu.toyouserver.dto.SocialAuthResponse;
import slvtwn.khu.toyouserver.dto.TokenResponse;
import slvtwn.khu.toyouserver.persistance.UserRepository;

@Service
@RequiredArgsConstructor
public class KakaoAuthStrategy implements SocialAuthStrategy {

private final AuthService authService;
@Value("${oauth.kakao.client-id}")
private String kakaoClientId;
@Value("${oauth.kakao.redirect-uri}")
private String kakaoRedirectUri;
@Value("${oauth.kakao.grant-type}")
private String grantType;

private final KakaoAuthApiClient kakaoAuthApiClient;
private final KakaoResourceApiClient kakaoResourceApiClient;

private final UserRepository userRepository;
private final UserOAuthCredentialRepository userOAuthCredentialRepository;

private final JwtTokenProvider jwtTokenProvider;

@Override
@Transactional
public SocialAuthResponse login(SocialAuthRequest request) {
KakaoTokenResponse tokenResponse = kakaoAuthApiClient.getOAuth2AccessToken(
grantType,
kakaoClientId,
kakaoRedirectUri,
request.authorizationCode()
);
KakaoUserResponse userResponse = kakaoResourceApiClient.getUserInformation(
"Bearer " + tokenResponse.accessToken());
User user = handleUserOAuthCredential(userResponse);
TokenResponse token = new TokenResponse(jwtTokenProvider.generateAccessToken(user.getId()),
jwtTokenProvider.generateRefreshToken(user.getId()));
return SocialAuthResponse.of(user.getId(), user.getName(), KAKAO, token);
}

@Override
public boolean support(String provider) {
return provider.equals("KAKAO");
}

private User handleUserOAuthCredential(KakaoUserResponse userResponse) {
UserOAuthCredential userOAuthCredential = userOAuthCredentialRepository.findBySerialId(userResponse.serialId())
.orElse(null);

User authenticatedUser;
if (userOAuthCredential == null) {
authenticatedUser = User.create(userResponse.kakaoAccount().profile().nickname(),
userResponse.kakaoAccount().profile().profileImageUrl());
userOAuthCredential = UserOAuthCredential.recordKAKAOCredential(authenticatedUser, userResponse.serialId());

userRepository.save(authenticatedUser);
userOAuthCredentialRepository.save(userOAuthCredential);
} else {
authenticatedUser = userOAuthCredential.getUser();
}
return authenticatedUser;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package slvtwn.khu.toyouserver.application.auth.strategy;

import slvtwn.khu.toyouserver.dto.SocialAuthRequest;
import slvtwn.khu.toyouserver.dto.SocialAuthResponse;

public interface SocialAuthStrategy {
SocialAuthResponse login(final SocialAuthRequest request);

boolean support(String provider);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package slvtwn.khu.toyouserver.presentation;

import static slvtwn.khu.toyouserver.common.response.ResponseType.NOT_SUPPORTED_AUTH_PROVIDER;

import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import slvtwn.khu.toyouserver.application.auth.SocialAuthContext;
import slvtwn.khu.toyouserver.common.response.ToyouResponse;
import slvtwn.khu.toyouserver.dto.SocialAuthRequest;
import slvtwn.khu.toyouserver.dto.SocialAuthResponse;
import slvtwn.khu.toyouserver.exception.ToyouException;

@RequiredArgsConstructor
@RequestMapping("/auth")
public class AuthController {

private final SocialAuthContext socialAuthContext;

@PostMapping("/login")
public ToyouResponse<SocialAuthResponse> login(@RequestBody SocialAuthRequest request) {
if (socialAuthContext.support(request.provider())) {
return ToyouResponse.from(socialAuthContext.doLogin(request));
}
throw new ToyouException(NOT_SUPPORTED_AUTH_PROVIDER);
}
}
8 changes: 7 additions & 1 deletion src/main/resources/application.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
spring:
jpa:
# database: mysql
# database: mysql
open-in-view: false
generate-ddl: true
show-sql: true
Expand All @@ -14,3 +14,9 @@ spring:
username: sa
password:

oauth:
kakao:
client-id: ${KAKAO_CLIENT_ID}
client-secret: ${KAKAO_CLIENT_SECRET}
grant-type: authorization_code
redirect-uri: ${KAKAO_REDIRECT_URI}

0 comments on commit 830f849

Please sign in to comment.