Skip to content

Commit 46d08c8

Browse files
authored
Merge pull request #169 from GoToBILL/fix
feat: OAuth 통합 컨트롤러 및 Facade 패턴을 구현했습니다
2 parents a290f9a + 7dd9feb commit 46d08c8

28 files changed

+1067
-296
lines changed

src/main/java/com/example/cherrydan/oauth/controller/AppleAuthController.java

Lines changed: 47 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -25,60 +25,62 @@
2525

2626
import java.util.Map;
2727

28+
@Deprecated(since = "2025.09", forRemoval = true)
2829
@Slf4j
2930
@RestController
30-
@RequestMapping("/api/auth/apple")
31+
// @RequestMapping("/api/auth/apple") // 통합 OAuthController 사용을 위해 주석 처리
3132
@RequiredArgsConstructor
32-
@Tag(name = "Apple 인증", description = "Apple Sign in with Apple 관련 API")
33+
@Tag(name = "Apple 인증 (Deprecated)", description = "새로운 OAuthController를 사용하세요")
3334
public class AppleAuthController {
3435

3536
private final AppleIdentityTokenService appleIdentityTokenService;
3637
private final CustomOAuth2UserService customOAuth2UserService;
3738
private final JwtTokenProvider jwtTokenProvider;
3839
private final RefreshTokenService refreshTokenService;
3940

40-
@PostMapping("/login")
41-
@Operation(summary = "Apple 로그인", description = "iOS에서 받은 Identity Token으로 Apple 로그인 처리")
42-
public ResponseEntity<ApiResponse<LoginResponse>> appleLogin(@RequestBody AppleLoginRequest request) {
43-
// 1. 입력 값 검증
44-
validateAppleLoginRequest(request);
45-
46-
// 2. Apple Identity Token 검증
47-
Map<String, Object> userInfo = appleIdentityTokenService.verifyIdentityToken(request.getAccessToken());
48-
49-
// 3. OAuth2UserInfo 객체 생성 (JWT 정보 + iOS 정보 결합)
50-
OAuth2UserInfo oAuth2UserInfo = new AppleOAuth2UserInfo(userInfo);
51-
52-
// 4. 사용자 조회 또는 생성 (CustomOAuth2UserService 사용)
53-
User user = customOAuth2UserService.processAppleUser(oAuth2UserInfo, request);
54-
55-
// 5. Access Token과 Refresh Token 생성
56-
TokenDTO tokenDTO = jwtTokenProvider.generateTokens(user.getId(), user.getEmail());
57-
58-
// 6. Refresh Token을 DB에 저장
59-
refreshTokenService.saveOrUpdateRefreshToken(user, tokenDTO.getRefreshToken());
41+
// 통합 OAuthController로 이동됨 - 참고용으로 주석 처리
42+
// @PostMapping("/login")
43+
// @Operation(summary = "Apple 로그인", description = "iOS에서 받은 Identity Token으로 Apple 로그인 처리")
44+
// public ResponseEntity<ApiResponse<LoginResponse>> appleLogin(@RequestBody AppleLoginRequest request) {
45+
// // 1. 입력 값 검증
46+
// validateAppleLoginRequest(request);
47+
//
48+
// // 2. Apple Identity Token 검증
49+
// Map<String, Object> userInfo = appleIdentityTokenService.verifyIdentityToken(request.getAccessToken());
50+
//
51+
// // 3. OAuth2UserInfo 객체 생성 (JWT 정보 + iOS 정보 결합)
52+
// OAuth2UserInfo oAuth2UserInfo = new AppleOAuth2UserInfo(userInfo);
53+
//
54+
// // 4. 사용자 조회 또는 생성 (CustomOAuth2UserService 사용)
55+
// User user = customOAuth2UserService.processAppleUser(oAuth2UserInfo, request);
56+
//
57+
// // 5. Access Token과 Refresh Token 생성
58+
// TokenDTO tokenDTO = jwtTokenProvider.generateTokens(user.getId(), user.getEmail());
59+
//
60+
// // 6. Refresh Token을 DB에 저장
61+
// refreshTokenService.saveOrUpdateRefreshToken(user, tokenDTO.getRefreshToken());
62+
//
63+
// log.info("Apple 로그인 성공: userId={}, email={}, name={}", user.getId(), user.getEmail(), user.getName());
64+
//
65+
// return ResponseEntity.ok(ApiResponse.success(new LoginResponse(tokenDTO,user.getId())));
66+
// }
6067

61-
log.info("Apple 로그인 성공: userId={}, email={}, name={}", user.getId(), user.getEmail(), user.getName());
62-
63-
return ResponseEntity.ok(ApiResponse.success(new LoginResponse(tokenDTO,user.getId())));
64-
}
65-
66-
/**
67-
* Apple 로그인 요청 검증
68-
*/
69-
private void validateAppleLoginRequest(AppleLoginRequest request) {
70-
if (request == null) {
71-
throw new AuthException(ErrorMessage.INVALID_REQUEST);
72-
}
73-
74-
if (!StringUtils.hasText(request.getAccessToken())) {
75-
throw new AuthException(ErrorMessage.APPLE_USER_INFO_MISSING);
76-
}
77-
78-
// JWT 형식 기본 검증 (3개 파트로 구성되어야 함)
79-
String[] tokenParts = request.getAccessToken().split("\\.");
80-
if (tokenParts.length != 3) {
81-
throw new AuthException(ErrorMessage.APPLE_IDENTITY_TOKEN_INVALID);
82-
}
83-
}
68+
// /**
69+
// * Apple 로그인 요청 검증
70+
// */
71+
// private void validateAppleLoginRequest(AppleLoginRequest request) {
72+
// if (request == null) {
73+
// throw new AuthException(ErrorMessage.INVALID_REQUEST);
74+
// }
75+
//
76+
// if (!StringUtils.hasText(request.getAccessToken())) {
77+
// throw new AuthException(ErrorMessage.APPLE_USER_INFO_MISSING);
78+
// }
79+
//
80+
// // JWT 형식 기본 검증 (3개 파트로 구성되어야 함)
81+
// String[] tokenParts = request.getAccessToken().split("\\.");
82+
// if (tokenParts.length != 3) {
83+
// throw new AuthException(ErrorMessage.APPLE_IDENTITY_TOKEN_INVALID);
84+
// }
85+
// }
8486
}

src/main/java/com/example/cherrydan/oauth/controller/GoogleAuthController.java

Lines changed: 74 additions & 72 deletions
Original file line numberDiff line numberDiff line change
@@ -24,85 +24,87 @@
2424
import org.springframework.web.bind.annotation.RequestMapping;
2525
import org.springframework.web.bind.annotation.RestController;
2626

27+
@Deprecated(since = "2025.09", forRemoval = true)
2728
@Slf4j
2829
@RestController
29-
@RequestMapping("/api/auth/google")
30+
// @RequestMapping("/api/auth/google") // 통합 OAuthController 사용을 위해 주석 처리
3031
@RequiredArgsConstructor
31-
@Tag(name = "Google 인증", description = "Google Sign-In 관련 API")
32+
@Tag(name = "Google 인증 (Deprecated)", description = "새로운 OAuthController를 사용하세요")
3233
public class GoogleAuthController {
3334
private final GoogleIdentityTokenService googleIdentityTokenService;
3435
private final CustomOAuth2UserService customOAuth2UserService;
3536
private final JwtTokenProvider jwtTokenProvider;
3637
private final RefreshTokenService refreshTokenService;
3738

38-
@PostMapping("/login")
39-
@Operation(
40-
summary = "Google 모바일 로그인/회원가입",
41-
description = """
42-
### Google 모바일 SDK를 통해 로그인 후, 받은 ID Token으로 서버에 로그인/회원가입을 요청하는 API 입니다.
43-
44-
**모바일 클라이언트 개발 순서:**
45-
1. 각 플랫폼(iOS/Android)에 맞는 Google Sign-In SDK를 사용하여 사용자의 구글 로그인을 처리합니다.
46-
2. 로그인 성공 시, Google로부터 **ID Token** 문자열을 발급받습니다.
47-
3. 발급받은 ID Token을 이 API의 Body에 담아 요청합니다.
48-
4. 요청 성공 시, 응답으로 받은 **accessToken**과 **refreshToken**을 앱 내 안전한 곳(e.g., Keychain, Keystore)에 저장합니다.
49-
5. 이후 저희 서비스의 다른 API를 호출할 때는, `Authorization` 헤더에 `Bearer {accessToken}` 형식으로 토큰을 담아 요청합니다.
50-
51-
---
52-
53-
**iOS (Swift) 요청 예시:**
54-
```swift
55-
guard let url = URL(string: "cherrydan.com/api/auth/google/login") else { return }
56-
var request = URLRequest(url: url)
57-
request.httpMethod = "POST"
58-
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
59-
60-
let body = ["idToken": "google_id_token_string"]
61-
request.httpBody = try? JSONEncoder().encode(body)
62-
63-
URLSession.shared.dataTask(with: request) { data, response, error in
64-
// Handle response...
65-
}.resume()
66-
```
67-
68-
**Android (Kotlin with Retrofit) 요청 예시:**
69-
```kotlin
70-
// Retrofit Interface
71-
interface ApiService {
72-
@POST("api/auth/google/login")
73-
suspend fun loginWithGoogle(@Body body: GoogleLoginRequest): Response<LoginResponse>
74-
}
75-
76-
// DTO
77-
data class GoogleLoginRequest(val idToken: String)
78-
79-
// ViewModel or Repository
80-
suspend fun performGoogleLogin(idToken: String) {
81-
val request = GoogleLoginRequest(idToken = idToken)
82-
val response = yourRetrofitService.loginWithGoogle(request)
83-
// Handle response...
84-
}
85-
```
86-
"""
87-
)
88-
public ResponseEntity<ApiResponse<LoginResponse>> googleLogin(@RequestBody GoogleLoginRequest request) {
89-
// 1. Google ID Token 검증
90-
GoogleIdToken.Payload payload = googleIdentityTokenService.verify(request.getAccessToken());
91-
92-
// 2. OAuth2UserInfo 객체 생성
93-
OAuth2UserInfo oAuth2UserInfo = new GoogleOAuth2UserInfo(payload);
94-
95-
// 3. 사용자 조회 또는 생성
96-
User user = customOAuth2UserService.processGoogleUser(oAuth2UserInfo, request);
97-
98-
// 4. Access Token과 Refresh Token 생성
99-
TokenDTO tokenDTO = jwtTokenProvider.generateTokens(user.getId(), user.getEmail());
100-
101-
// 5. Refresh Token을 DB에 저장
102-
refreshTokenService.saveOrUpdateRefreshToken(user, tokenDTO.getRefreshToken());
103-
104-
log.info("Google 모바일 로그인 성공: userId={}, email={}, name={}", user.getId(), user.getEmail(), user.getName());
105-
106-
return ResponseEntity.ok(ApiResponse.success(new LoginResponse(tokenDTO, user.getId())));
107-
}
39+
// 통합 OAuthController로 이동됨 - 참고용으로 주석 처리
40+
// @PostMapping("/login")
41+
// @Operation(
42+
// summary = "Google 모바일 로그인/회원가입",
43+
// description = """
44+
// ### Google 모바일 SDK를 통해 로그인 후, 받은 ID Token으로 서버에 로그인/회원가입을 요청하는 API 입니다.
45+
//
46+
// **모바일 클라이언트 개발 순서:**
47+
// 1. 각 플랫폼(iOS/Android)에 맞는 Google Sign-In SDK를 사용하여 사용자의 구글 로그인을 처리합니다.
48+
// 2. 로그인 성공 시, Google로부터 **ID Token** 문자열을 발급받습니다.
49+
// 3. 발급받은 ID Token을 이 API의 Body에 담아 요청합니다.
50+
// 4. 요청 성공 시, 응답으로 받은 **accessToken**과 **refreshToken**을 앱 내 안전한 곳(e.g., Keychain, Keystore)에 저장합니다.
51+
// 5. 이후 저희 서비스의 다른 API를 호출할 때는, `Authorization` 헤더에 `Bearer {accessToken}` 형식으로 토큰을 담아 요청합니다.
52+
//
53+
// ---
54+
//
55+
// **iOS (Swift) 요청 예시:**
56+
// ```swift
57+
// guard let url = URL(string: "cherrydan.com/api/auth/google/login") else { return }
58+
// var request = URLRequest(url: url)
59+
// request.httpMethod = "POST"
60+
// request.setValue("application/json", forHTTPHeaderField: "Content-Type")
61+
//
62+
// let body = ["idToken": "google_id_token_string"]
63+
// request.httpBody = try? JSONEncoder().encode(body)
64+
//
65+
// URLSession.shared.dataTask(with: request) { data, response, error in
66+
// // Handle response...
67+
// }.resume()
68+
// ```
69+
//
70+
// **Android (Kotlin with Retrofit) 요청 예시:**
71+
// ```kotlin
72+
// // Retrofit Interface
73+
// interface ApiService {
74+
// @POST("api/auth/google/login")
75+
// suspend fun loginWithGoogle(@Body body: GoogleLoginRequest): Response<LoginResponse>
76+
// }
77+
//
78+
// // DTO
79+
// data class GoogleLoginRequest(val idToken: String)
80+
//
81+
// // ViewModel or Repository
82+
// suspend fun performGoogleLogin(idToken: String) {
83+
// val request = GoogleLoginRequest(idToken = idToken)
84+
// val response = yourRetrofitService.loginWithGoogle(request)
85+
// // Handle response...
86+
// }
87+
// ```
88+
// """
89+
// )
90+
// public ResponseEntity<ApiResponse<LoginResponse>> googleLogin(@RequestBody GoogleLoginRequest request) {
91+
// // 1. Google ID Token 검증
92+
// GoogleIdToken.Payload payload = googleIdentityTokenService.verify(request.getAccessToken());
93+
//
94+
// // 2. OAuth2UserInfo 객체 생성
95+
// OAuth2UserInfo oAuth2UserInfo = new GoogleOAuth2UserInfo(payload);
96+
//
97+
// // 3. 사용자 조회 또는 생성
98+
// User user = customOAuth2UserService.processGoogleUser(oAuth2UserInfo, request);
99+
//
100+
// // 4. Access Token과 Refresh Token 생성
101+
// TokenDTO tokenDTO = jwtTokenProvider.generateTokens(user.getId(), user.getEmail());
102+
//
103+
// // 5. Refresh Token을 DB에 저장
104+
// refreshTokenService.saveOrUpdateRefreshToken(user, tokenDTO.getRefreshToken());
105+
//
106+
// log.info("Google 모바일 로그인 성공: userId={}, email={}, name={}", user.getId(), user.getEmail(), user.getName());
107+
//
108+
// return ResponseEntity.ok(ApiResponse.success(new LoginResponse(tokenDTO, user.getId())));
109+
// }
108110
}

0 commit comments

Comments
 (0)