Book 469 feature/#141#151
Conversation
- 테스트 프로필에 oauth 설정 추가 - 로컬에서 sonar task 스킵되도록 수정
WalkthroughGoogle ID 토큰 검증을 위한 새로운 인증 전략을 도입합니다. 기존의 Google API Manager 기반 접근에서 Google ID 토큰 프로세서로 전환하여 GoogleOauthProperties에 clientId를 추가하고, 필수 Google 클라이언트 라이브러리를 포함합니다. Changes
Sequence DiagramsequenceDiagram
participant Client as 클라이언트
participant SignInStrategy as GoogleSignInStrategy
participant Processor as GoogleIdTokenProcessor
participant Verifier as GoogleIdTokenVerifier
participant ExceptionHandler as 예외 처리
Client->>SignInStrategy: authenticate(idToken)
SignInStrategy->>Processor: parseAndValidate(idToken)
Processor->>Verifier: verify(idToken)
alt 토큰 검증 성공
Verifier-->>Processor: GoogleIdToken.Payload
Processor-->>SignInStrategy: payload
SignInStrategy->>SignInStrategy: createUserInfo(payload)
SignInStrategy-->>Client: UserCreateInfoResponse
else 토큰 검증 실패
Verifier-->>Processor: 예외 발생
Processor->>ExceptionHandler: AuthException(INVALID_GOOGLE_ID_TOKEN)
ExceptionHandler-->>Client: 에러 응답
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes 🚥 Pre-merge checks | ✅ 1 | ❌ 2❌ Failed checks (1 warning, 1 inconclusive)
✅ Passed checks (1 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
apis/src/main/resources/application.yml (1)
95-98: test 프로파일에client-id설정이 누락되었습니다.
GoogleOauthProperties는clientId를 필수 속성으로 요구합니다. test 프로파일에는url.user-info만 설정되어 있고client-id가 누락되어 있어, 애플리케이션 컨텍스트 로드 시 바인딩 실패가 발생할 수 있습니다.🔧 제안하는 수정
oauth: google: url: user-info: https://www.googleapis.com/oauth2/v2/userinfo + client-id: test-client-id
🤖 Fix all issues with AI agents
In `@apis/src/main/kotlin/org/yapp/apis/auth/exception/AuthErrorCode.kt`:
- Around line 22-26: The enum entries INVALID_APPLE_ID_TOKEN,
INVALID_GOOGLE_ID_TOKEN, PROVIDER_TYPE_MISMATCH, APPLE_REFRESH_TOKEN_MISSING,
and KAKAO_UNLINK_FAILED are out of numeric order; reorder these constants so
their error codes are in ascending sequence (e.g., move INVALID_GOOGLE_ID_TOKEN
(AUTH_400_13) after PROVIDER_TYPE_MISMATCH (AUTH_400_11) or otherwise arrange
AUTH_400_10 → AUTH_400_11 → AUTH_400_12 → AUTH_400_13 → AUTH_400_15) and verify
whether an AUTH_400_14 entry is missing—add or account for AUTH_400_14 if
required to keep the numeric sequence contiguous; update only the enum constant
order in AuthErrorCode to maintain code clarity.
In
`@apis/src/main/kotlin/org/yapp/apis/auth/helper/google/GoogleIdTokenProcessor.kt`:
- Around line 24-33: The parseAndValidate method loses original exception
context and can double-wrap AuthException; fix by either (preferred) adding a
cause parameter to AuthException's constructor (e.g., class AuthException(...,
cause: Throwable? = null) : CommonException(...)) and when catching exceptions
in GoogleIdTokenProcessor.parseAndValidate pass the original exception as the
cause, or modify parseAndValidate to explicitly rethrow AuthException (catch
AuthException and throw it) and only wrap other Exceptions into a new
AuthException; reference the parseAndValidate function and the AuthException
class when making the change.
In `@buildSrc/src/main/kotlin/Dependencies.kt`:
- Around line 84-88: Update the Google dependency constants to the latest stable
versions: change the value of API_CLIENT to use version 2.8.0, and update
HTTP_CLIENT_APACHE and HTTP_CLIENT_GSON to use version 1.47.0; edit the object
Google constants API_CLIENT, HTTP_CLIENT_APACHE, and HTTP_CLIENT_GSON in
Dependencies.kt to reflect these new version strings.
| INVALID_APPLE_ID_TOKEN(HttpStatus.BAD_REQUEST, "AUTH_400_10", "유효하지 않은 Apple ID 토큰입니다."), | ||
| INVALID_GOOGLE_ID_TOKEN(HttpStatus.BAD_REQUEST, "AUTH_400_13", "유효하지 않은 Google ID 토큰입니다."), | ||
| PROVIDER_TYPE_MISMATCH(HttpStatus.BAD_REQUEST, "AUTH_400_11", "요청된 공급자 타입이 실제 사용자의 공급자 타입과 일치하지 않습니다."), | ||
| APPLE_REFRESH_TOKEN_MISSING(HttpStatus.BAD_REQUEST, "AUTH_400_12", "Apple 사용자 탈퇴 시 리프레시 토큰이 누락되었습니다."), | ||
| KAKAO_UNLINK_FAILED(HttpStatus.BAD_REQUEST, "AUTH_400_15", "카카오 회원탈퇴 처리에 실패했습니다."), |
There was a problem hiding this comment.
🧹 Nitpick | 🔵 Trivial
에러 코드 순서가 일관성 없이 배치되어 있습니다.
INVALID_GOOGLE_ID_TOKEN (AUTH_400_13)이 AUTH_400_10과 AUTH_400_11 사이에 배치되어 있어 코드 번호 순서와 맞지 않습니다. 또한 AUTH_400_14가 건너뛰어졌는지 확인이 필요합니다.
가독성과 유지보수를 위해 에러 코드 번호 순서대로 정렬하는 것을 권장합니다.
♻️ 순서 정렬 제안
INVALID_APPLE_ID_TOKEN(HttpStatus.BAD_REQUEST, "AUTH_400_10", "유효하지 않은 Apple ID 토큰입니다."),
- INVALID_GOOGLE_ID_TOKEN(HttpStatus.BAD_REQUEST, "AUTH_400_13", "유효하지 않은 Google ID 토큰입니다."),
PROVIDER_TYPE_MISMATCH(HttpStatus.BAD_REQUEST, "AUTH_400_11", "요청된 공급자 타입이 실제 사용자의 공급자 타입과 일치하지 않습니다."),
APPLE_REFRESH_TOKEN_MISSING(HttpStatus.BAD_REQUEST, "AUTH_400_12", "Apple 사용자 탈퇴 시 리프레시 토큰이 누락되었습니다."),
+ INVALID_GOOGLE_ID_TOKEN(HttpStatus.BAD_REQUEST, "AUTH_400_13", "유효하지 않은 Google ID 토큰입니다."),
KAKAO_UNLINK_FAILED(HttpStatus.BAD_REQUEST, "AUTH_400_15", "카카오 회원탈퇴 처리에 실패했습니다."),📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| INVALID_APPLE_ID_TOKEN(HttpStatus.BAD_REQUEST, "AUTH_400_10", "유효하지 않은 Apple ID 토큰입니다."), | |
| INVALID_GOOGLE_ID_TOKEN(HttpStatus.BAD_REQUEST, "AUTH_400_13", "유효하지 않은 Google ID 토큰입니다."), | |
| PROVIDER_TYPE_MISMATCH(HttpStatus.BAD_REQUEST, "AUTH_400_11", "요청된 공급자 타입이 실제 사용자의 공급자 타입과 일치하지 않습니다."), | |
| APPLE_REFRESH_TOKEN_MISSING(HttpStatus.BAD_REQUEST, "AUTH_400_12", "Apple 사용자 탈퇴 시 리프레시 토큰이 누락되었습니다."), | |
| KAKAO_UNLINK_FAILED(HttpStatus.BAD_REQUEST, "AUTH_400_15", "카카오 회원탈퇴 처리에 실패했습니다."), | |
| INVALID_APPLE_ID_TOKEN(HttpStatus.BAD_REQUEST, "AUTH_400_10", "유효하지 않은 Apple ID 토큰입니다."), | |
| PROVIDER_TYPE_MISMATCH(HttpStatus.BAD_REQUEST, "AUTH_400_11", "요청된 공급자 타입이 실제 사용자의 공급자 타입과 일치하지 않습니다."), | |
| APPLE_REFRESH_TOKEN_MISSING(HttpStatus.BAD_REQUEST, "AUTH_400_12", "Apple 사용자 탈퇴 시 리프레시 토큰이 누락되었습니다."), | |
| INVALID_GOOGLE_ID_TOKEN(HttpStatus.BAD_REQUEST, "AUTH_400_13", "유효하지 않은 Google ID 토큰입니다."), | |
| KAKAO_UNLINK_FAILED(HttpStatus.BAD_REQUEST, "AUTH_400_15", "카카오 회원탈퇴 처리에 실패했습니다."), |
🤖 Prompt for AI Agents
In `@apis/src/main/kotlin/org/yapp/apis/auth/exception/AuthErrorCode.kt` around
lines 22 - 26, The enum entries INVALID_APPLE_ID_TOKEN, INVALID_GOOGLE_ID_TOKEN,
PROVIDER_TYPE_MISMATCH, APPLE_REFRESH_TOKEN_MISSING, and KAKAO_UNLINK_FAILED are
out of numeric order; reorder these constants so their error codes are in
ascending sequence (e.g., move INVALID_GOOGLE_ID_TOKEN (AUTH_400_13) after
PROVIDER_TYPE_MISMATCH (AUTH_400_11) or otherwise arrange AUTH_400_10 →
AUTH_400_11 → AUTH_400_12 → AUTH_400_13 → AUTH_400_15) and verify whether an
AUTH_400_14 entry is missing—add or account for AUTH_400_14 if required to keep
the numeric sequence contiguous; update only the enum constant order in
AuthErrorCode to maintain code clarity.
| fun parseAndValidate(idToken: String): GoogleIdToken.Payload { | ||
| try { | ||
| val googleIdToken = verifier.verify(idToken) | ||
| ?: throw AuthException(AuthErrorCode.INVALID_GOOGLE_ID_TOKEN, "Invalid ID token") | ||
|
|
||
| return googleIdToken.payload | ||
| } catch (e: Exception) { | ||
| throw AuthException(AuthErrorCode.INVALID_GOOGLE_ID_TOKEN, e.message) | ||
| } | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
find . -type f -name "*.kt" -o -name "*.java" | xargs grep -l "class AuthException" | head -5Repository: YAPP-Github/Reed-Server
Length of output: 135
🏁 Script executed:
rg "class AuthException" -A 10 --max-count 5Repository: YAPP-Github/Reed-Server
Length of output: 453
🏁 Script executed:
cat -n apis/src/main/kotlin/org/yapp/apis/auth/exception/AuthException.ktRepository: YAPP-Github/Reed-Server
Length of output: 334
🏁 Script executed:
rg "class CommonException" -A 10Repository: YAPP-Github/Reed-Server
Length of output: 809
🏁 Script executed:
cat -n global-utils/src/main/kotlin/org/yapp/globalutils/exception/CommonException.ktRepository: YAPP-Github/Reed-Server
Length of output: 436
🏁 Script executed:
rg "class ResponseStatusException" -A 5 --max-count 3Repository: YAPP-Github/Reed-Server
Length of output: 49
🏁 Script executed:
cat -n apis/src/main/kotlin/org/yapp/apis/auth/helper/google/GoogleIdTokenProcessor.kt | head -40Repository: YAPP-Github/Reed-Server
Length of output: 1599
예외 처리 로직 개선 필요
현재 예외 처리에 두 가지 문제가 있습니다:
-
예외 정보 손실: 원본 예외
e가 전달되지 않아 스택 트레이스가 유실됩니다. -
불필요한 이중 래핑: 27번 줄의
AuthException이 30번 줄 catch 블록에서 다시 잡혀 재래핑됩니다.
AuthException이 현재 cause 파라미터를 지원하지 않으므로, 다음 중 한 가지 방식으로 개선하시기 바랍니다:
방안 1 (권장): AuthException 생성자에 cause 파라미터 추가 후 예외 원인 전달
class AuthException(
errorCode: AuthErrorCode,
message: String? = null,
cause: Throwable? = null
) : CommonException(errorCode, message)방안 2: AuthException을 별도로 처리하여 이중 래핑 방지
fun parseAndValidate(idToken: String): GoogleIdToken.Payload = try {
verifier.verify(idToken)?.payload
?: throw AuthException(AuthErrorCode.INVALID_GOOGLE_ID_TOKEN, "Invalid ID token")
} catch (e: AuthException) {
throw e
} catch (e: Exception) {
throw AuthException(AuthErrorCode.INVALID_GOOGLE_ID_TOKEN, e.message)
}🧰 Tools
🪛 detekt (1.23.8)
[warning] 30-30: The caught exception is too generic. Prefer catching specific exceptions to the case that is currently handled.
(detekt.exceptions.TooGenericExceptionCaught)
[warning] 30-30: The caught exception is swallowed. The original exception could be lost.
(detekt.exceptions.SwallowedException)
🤖 Prompt for AI Agents
In
`@apis/src/main/kotlin/org/yapp/apis/auth/helper/google/GoogleIdTokenProcessor.kt`
around lines 24 - 33, The parseAndValidate method loses original exception
context and can double-wrap AuthException; fix by either (preferred) adding a
cause parameter to AuthException's constructor (e.g., class AuthException(...,
cause: Throwable? = null) : CommonException(...)) and when catching exceptions
in GoogleIdTokenProcessor.parseAndValidate pass the original exception as the
cause, or modify parseAndValidate to explicitly rethrow AuthException (catch
AuthException and throw it) and only wrap other Exceptions into a new
AuthException; reference the parseAndValidate function and the AuthException
class when making the change.
| object Google { | ||
| const val API_CLIENT = "com.google.api-client:google-api-client:2.2.0" | ||
| const val HTTP_CLIENT_APACHE = "com.google.http-client:google-http-client-apache-v2:1.43.3" | ||
| const val HTTP_CLIENT_GSON = "com.google.http-client:google-http-client-gson:1.43.3" | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
echo "=== Checking latest versions from Maven Central ==="
echo "google-api-client:"
curl -s "https://search.maven.org/solrsearch/select?q=g:com.google.api-client+AND+a:google-api-client&rows=1&wt=json" 2>/dev/null | jq -r '.response.docs[0].latestVersion' 2>/dev/null || echo "Unable to fetch"
echo ""
echo "google-http-client-apache-v2:"
curl -s "https://search.maven.org/solrsearch/select?q=g:com.google.http-client+AND+a:google-http-client-apache-v2&rows=1&wt=json" 2>/dev/null | jq -r '.response.docs[0].latestVersion' 2>/dev/null || echo "Unable to fetch"
echo ""
echo "google-http-client-gson:"
curl -s "https://search.maven.org/solrsearch/select?q=g:com.google.http-client+AND+a:google-http-client-gson&rows=1&wt=json" 2>/dev/null | jq -r '.response.docs[0].latestVersion' 2>/dev/null || echo "Unable to fetch"
echo ""
echo "=== Checking specific version details ==="
echo "google-api-client 2.2.0 details:"
curl -s "https://search.maven.org/solrsearch/select?q=g:com.google.api-client+AND+a:google-api-client+AND+v:2.2.0&rows=1&wt=json" 2>/dev/null | jq '.response.docs[0] | {id, latestVersion}' 2>/dev/null || echo "Unable to fetch"
echo ""
echo "google-http-client 1.43.3 details:"
curl -s "https://search.maven.org/solrsearch/select?q=g:com.google.http-client+AND+v:1.43.3&rows=5&wt=json" 2>/dev/null | jq '.response.docs[] | {id}' 2>/dev/null || echo "Unable to fetch"Repository: YAPP-Github/Reed-Server
Length of output: 751
Google 의존성 버전을 최신 안정 버전으로 업데이트하세요.
현재 사용 중인 버전들이 Maven Central의 최신 버전보다 뒤떨어져 있습니다:
google-api-client: 2.2.0 → 2.8.0 (업데이트 필요)google-http-client-apache-v2: 1.43.3 → 1.47.0 (업데이트 필요)google-http-client-gson: 1.43.3 → 1.47.0 (업데이트 필요)
최신 버전으로 업데이트하여 최신 기능 및 보안 패치를 적용하세요.
🤖 Prompt for AI Agents
In `@buildSrc/src/main/kotlin/Dependencies.kt` around lines 84 - 88, Update the
Google dependency constants to the latest stable versions: change the value of
API_CLIENT to use version 2.8.0, and update HTTP_CLIENT_APACHE and
HTTP_CLIENT_GSON to use version 1.47.0; edit the object Google constants
API_CLIENT, HTTP_CLIENT_APACHE, and HTTP_CLIENT_GSON in Dependencies.kt to
reflect these new version strings.
🔗 관련 이슈
📘 작업 유형
📙 작업 내역
🧪 테스트 내역
🎨 스크린샷 또는 시연 영상 (선택)
✅ PR 체크리스트
💬 추가 설명 or 리뷰 포인트 (선택)
Summary by CodeRabbit
릴리스 노트
새로운 기능
버그 수정
설정
✏️ Tip: You can customize this high-level summary in your review settings.