Skip to content

Book 469 feature/#141#151

Merged
minwoo1999 merged 5 commits intodevelopfrom
BOOK-469-feature/#141
Jan 26, 2026
Merged

Book 469 feature/#141#151
minwoo1999 merged 5 commits intodevelopfrom
BOOK-469-feature/#141

Conversation

@minwoo1999
Copy link
Copy Markdown
Member

@minwoo1999 minwoo1999 commented Jan 26, 2026

🔗 관련 이슈

  • Close #

📘 작업 유형

  • ✨ Feature (기능 추가)
  • 🐞 Bugfix (버그 수정)
  • 🔧 Refactor (코드 리팩토링)
  • ⚙️ Chore (환경 설정)
  • 📝 Docs (문서 작성 및 수정)
  • ✅ Test (기능 테스트)
  • 🎨 style (코드 스타일 수정)

📙 작업 내역

🧪 테스트 내역

  • 브라우저/기기에서 동작 확인
  • 엣지 케이스 테스트 완료
  • 기존 기능 영향 없음

🎨 스크린샷 또는 시연 영상 (선택)

기능 미리보기 기능 미리보기
기능 설명 기능 설명

✅ PR 체크리스트

  • 커밋 메시지가 명확합니다
  • PR 제목이 컨벤션에 맞습니다
  • 관련 이슈 번호를 작성했습니다
  • 기능이 정상적으로 작동합니다
  • 불필요한 코드를 제거했습니다

💬 추가 설명 or 리뷰 포인트 (선택)

  • ..

Summary by CodeRabbit

릴리스 노트

  • 새로운 기능

    • Google 로그인 인증 과정에서 ID 토큰 검증 기능 추가
  • 버그 수정

    • 유효하지 않은 Google ID 토큰에 대한 오류 감지 및 처리 개선
  • 설정

    • Google OAuth 구성에 클라이언트 ID 환경 변수(GOOGLE_CLIENT_ID) 설정 필수

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jan 26, 2026

Walkthrough

Google ID 토큰 검증을 위한 새로운 인증 전략을 도입합니다. 기존의 Google API Manager 기반 접근에서 Google ID 토큰 프로세서로 전환하여 GoogleOauthProperties에 clientId를 추가하고, 필수 Google 클라이언트 라이브러리를 포함합니다.

Changes

코호트 / 파일(들) 변경 사항
의존성 및 설정
buildSrc/src/main/kotlin/Dependencies.kt, apis/build.gradle.kts, apis/src/main/resources/application.yml, apis/src/main/kotlin/org/yapp/apis/config/GoogleOauthProperties.kt
Google API 클라이언트 라이브러리 3개 추가(API Client, HTTP Client Apache, HTTP Client Gson); 빌드 gradle에 의존성 선언; application.yml에 client-id 환경 변수 설정; GoogleOauthProperties에 clientId 필드 추가
Google ID 토큰 검증 로직
apis/src/main/kotlin/org/yapp/apis/auth/helper/google/GoogleIdTokenProcessor.kt
새 클래스 추가: Google ID 토큰 검증을 위해 GoogleIdTokenVerifier를 사용하는 GoogleIdTokenProcessor; parseAndValidate() 메서드로 토큰 파싱 및 검증 수행
인증 전략 업데이트
apis/src/main/kotlin/org/yapp/apis/auth/strategy/signin/GoogleSignInStrategy.kt, apis/src/main/kotlin/org/yapp/apis/auth/strategy/signin/SignInCredentials.kt
GoogleSignInStrategy에서 GoogleApiManager를 GoogleIdTokenProcessor로 교체; 인증 흐름을 ID 토큰 검증 기반으로 변경; GoogleAuthCredentials의 accessToken을 idToken으로 변경; 사용자 정보 필드 매핑 업데이트(subject, picture 활용)
에러 처리
apis/src/main/kotlin/org/yapp/apis/auth/exception/AuthErrorCode.kt
새 enum 상수 추가: INVALID_GOOGLE_ID_TOKEN(BAD_REQUEST, "AUTH_400_13")

Sequence Diagram

sequenceDiagram
    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
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 1 | ❌ 2
❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive PR 제목이 기본 변경 사항과 명확하게 관련되어 있지 않습니다. 'Book 469 feature/#141'은 이슈 번호와 브랜치명을 참조할 뿐, Google 소셜 로그인 구현이라는 실제 주요 변경 사항을 설명하지 않습니다. PR 제목을 'Implement Google social login with ID token validation' 또는 유사한 형식으로 수정하여 Google 소셜 로그인 기능 구현이라는 주요 변경 사항을 명확하게 전달하세요.
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 설정이 누락되었습니다.

GoogleOauthPropertiesclientId를 필수 속성으로 요구합니다. 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.

Comment on lines 22 to 26
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", "카카오 회원탈퇴 처리에 실패했습니다."),
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick | 🔵 Trivial

에러 코드 순서가 일관성 없이 배치되어 있습니다.

INVALID_GOOGLE_ID_TOKEN (AUTH_400_13)이 AUTH_400_10AUTH_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.

Suggested change
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.

Comment on lines +24 to +33
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)
}
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

find . -type f -name "*.kt" -o -name "*.java" | xargs grep -l "class AuthException" | head -5

Repository: YAPP-Github/Reed-Server

Length of output: 135


🏁 Script executed:

rg "class AuthException" -A 10 --max-count 5

Repository: YAPP-Github/Reed-Server

Length of output: 453


🏁 Script executed:

cat -n apis/src/main/kotlin/org/yapp/apis/auth/exception/AuthException.kt

Repository: YAPP-Github/Reed-Server

Length of output: 334


🏁 Script executed:

rg "class CommonException" -A 10

Repository: YAPP-Github/Reed-Server

Length of output: 809


🏁 Script executed:

cat -n global-utils/src/main/kotlin/org/yapp/globalutils/exception/CommonException.kt

Repository: YAPP-Github/Reed-Server

Length of output: 436


🏁 Script executed:

rg "class ResponseStatusException" -A 5 --max-count 3

Repository: 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 -40

Repository: YAPP-Github/Reed-Server

Length of output: 1599


예외 처리 로직 개선 필요

현재 예외 처리에 두 가지 문제가 있습니다:

  1. 예외 정보 손실: 원본 예외 e가 전달되지 않아 스택 트레이스가 유실됩니다.

  2. 불필요한 이중 래핑: 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.

Comment on lines +84 to +88
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"
}
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 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.

@minwoo1999 minwoo1999 merged commit 184b168 into develop Jan 26, 2026
2 of 3 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Feb 8, 2026
15 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant