Skip to content

Comments

[Refactor] Auth 관련 API 네이밍 수정#609

Open
mono0801 wants to merge 8 commits intodevfrom
refactor/oauth2-api-url
Open

[Refactor] Auth 관련 API 네이밍 수정#609
mono0801 wants to merge 8 commits intodevfrom
refactor/oauth2-api-url

Conversation

@mono0801
Copy link
Contributor

@mono0801 mono0801 commented Feb 23, 2026

History

🚀 Major Changes & Explanations

  • OAuth2 로그인 및 Token 관련 API를 Customer와 Seller 둘 다 사용해야 하므로 API 네이밍을 변경하였습니다.
  • /seller/oauth2 > /oauth
기능 변경 전 변경 후
Kakao 로그인 /api/v1/seller/oauth2/authorization/kakao /api/v1/oauth/authorization/kakao
Google 로그인 /api/v1/seller/oauth2/authorization/google /api/v1/oauth/authorization/google
토큰 재발급 /api/v1/seller/oauth2/reissue /api/v1/auth/reissue
로그아웃 /api/v1/seller/oauth2/logout /api/v1/auth/logout

📷 Test Image

💡 ETC

  • 일단, OAuth2 API는 /oauth로 설정하였고 토큰 관련은 /auth로 설정하였습니다.
    • API Prefix 전부 /oauth로 통일할지 구분할지 생각중인데 어떻게 생각하시나요?
  • Store와 Seller의 연관관계를 1:1로 변경하면서 이와 관련된 테스트코드를 제거하였습니다.

Summary by CodeRabbit

  • New Features

    • OAuth 인증 엔드포인트 추가: 로그인, 토큰 재발급, 로그아웃 제공
    • 토큰 재발급 시 Authorization 헤더 갱신 및 리프레시 토큰 쿠키 자동 설정/갱신
  • Refactor

    • 토큰 생성·검증 로직 중앙화로 흐름 단순화 및 일관성 향상
    • 판매자용 OAuth 흐름 일부 정리 및 책임 분리
  • Tests

    • OAuth 인증 및 토큰 흐름에 대한 단위·통합 테스트 대폭 추가/갱신

@mono0801 mono0801 self-assigned this Feb 23, 2026
@mono0801 mono0801 linked an issue Feb 23, 2026 that may be closed by this pull request
1 task
@mono0801 mono0801 changed the title Refactor/oauth2 api url [Refactor] Auth 관련 API 네이밍 수정 Feb 23, 2026
@mono0801 mono0801 marked this pull request as ready for review February 23, 2026 15:05
@coderabbitai
Copy link

coderabbitai bot commented Feb 23, 2026

Walkthrough

새로운 Public OAuth 엔드포인트(/api/v1/oauth/api/v1/auth)와 이를 처리하는 컨트롤러/인터페이스/페사드/서비스를 추가하고, 판매자 전용의 토큰 재발급·로그아웃 로직을 제거하여 토큰 관련 로직을 중앙화했습니다. 보안 경로 및 쿠키 유틸, 관련 테스트가 추가·수정되었습니다.

Changes

Cohort / File(s) Summary
OAuth 컨트롤러/API
src/main/java/.../auth/oauth/client/controller/OAuthController.java, src/main/java/.../auth/oauth/client/controller/swagger/OAuthApi.java
새 OAuthController 및 Swagger API 추가: 로그인(리다이렉트), reissueToken(쿠키의 refreshToken → 페사드 위임 → Authorization 헤더·refreshToken 쿠키 갱신), logout(쿠키 삭제) 엔드포인트 추가.
OAuth 페사드/서비스
src/main/java/.../auth/oauth/client/facade/OAuthFacade.java, src/main/java/.../auth/oauth/client/service/OAuthService.java
OAuthFacade: refresh 토큰 파싱·검증·교체 흐름 구현. OAuthService: refresh/access 토큰 생성·검증·삭제 구현 및 토큰 만료 기간 사용(REFRESH=14일, ACCESS=3시간).
판매자 측 리팩토링
src/main/java/.../auth/seller/controller/SellerOauthController.java, src/main/java/.../auth/seller/controller/swagger/SellerOauthApi.java, src/main/java/.../auth/seller/service/OAuthSellerService.java, src/main/java/.../auth/seller/facade/OAuth2SellerFacade.java
판매자 전용 로그인/재발급/로그아웃 API 제거. OAuthSellerService에서 토큰 관련 로직 제거(판매자 정보 조회 전용 유지). OAuth2SellerFacade는 TokenProvider 의존성을 제거하고 OAuthService로 토큰 생성 위임, reissue 제거.
보안 경로/필터 업데이트
src/main/java/.../config/security/OAuth2SecurityConfig.java, src/main/java/.../config/security/PublicApiPath.java, src/main/java/.../config/security/auth/CustomOAuth2AuthorizationRequestResolver.java, src/main/java/.../config/security/auth/OAuth2ClientValidationFilter.java
PublicApiPath에 OAUTH_PREFIX/AUTH_PREFIX 추가 및 OAuth 관련 경로 매칭을 해당 상수로 통합; 필터 및 리졸버가 새 경로 상수를 사용하도록 변경.
유틸리티
src/main/java/.../util/CookieUtils.java
refreshToken 쿠키 생성 유틸 추가(httponly, secure, SameSite=Strict, 경로 및 만료 Duration 사용).
토큰 상수
src/main/java/.../config/security/jwt/TokenProvider.java
토큰 만료 상수 추가: REFRESH_TOKEN_DURATION(14일), ACCESS_TOKEN_DURATION(3시간).
테스트 추가/수정
src/test/java/.../auth/oauth/client/..., src/test/java/.../auth/seller/..., src/test/java/.../fixture/oauth/CookieFixture.java
OAuthController/Facade/Service에 대한 단·통합 테스트 추가. 판매자 관련 토큰 재발급·로그아웃 테스트 제거 및 관련 테스트 리팩토링. CookieFixture 추가.

Sequence Diagram(s)

sequenceDiagram
    participant Client as Client
    participant Controller as OAuthController
    participant Facade as OAuthFacade
    participant Service as OAuthService
    participant Repo as RefreshTokenRepository
    participant TokenProv as TokenProvider

    Client->>Controller: POST /api/v1/auth/reissue (cookie: refreshToken)
    Controller->>Facade: reissueToken(refreshToken)
    Facade->>TokenProv: parseRefreshToken(refreshToken)
    TokenProv-->>Facade: TokenClaims(userId, role)
    Facade->>Service: refreshTokenValidate(refreshToken)
    Service->>Repo: findByRefreshToken(refreshToken)
    Repo-->>Service: RefreshToken entity (exists)
    Facade->>Service: deleteRefreshToken(refreshToken)
    Service->>Repo: deleteByRefreshToken(refreshToken)
    Facade->>Service: generateRefreshToken(userId, role)
    Service->>TokenProv: generateToken(claims, duration=REFRESH_TOKEN_DURATION)
    TokenProv-->>Service: newRefreshToken
    Facade->>Service: generateAccessToken(userId, role)
    Service->>TokenProv: generateToken(claims, duration=ACCESS_TOKEN_DURATION)
    TokenProv-->>Service: newAccessToken
    Facade-->>Controller: TokenResponse(access, refresh)
    Controller->>Client: 200 OK (Header: Authorization, Set-Cookie: refreshToken)
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

  • [Refactor] OAuth2 API URL 변경 #606: OAuth 엔드포인트를 판매자 전용에서 공용 경로(/api/v1/oauth, /api/v1/auth)로 이동하는 URL 리팩토링 목표와 일치합니다.

Possibly related PRs

Suggested labels

test

Suggested reviewers

  • kmindev
  • kimjongsoo97
  • CUCU7103

시 🐰

새 길 따라 토큰을 굴려요,
쿠키 살포시 품에 안기고,
페사드가 솜씨 좋게 바꿔주니,
컨트롤러는 웃으며 응답하네,
당근 한 조각 축하의 껑충! 🥕🐇

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

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.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed PR 제목은 OAuth2 API 경로 네이밍 변경이라는 주요 변경 사항을 정확히 요약하고 있으며, Refactor 태그로 변경 유형을 명확히 표시하고 있습니다.
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 (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch refactor/oauth2-api-url

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

@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 (2)
src/main/java/com/bbangle/bbangle/config/security/PublicApiPath.java (1)

9-9: ⚠️ Potential issue | 🟡 Minor

/api/v1/oauth/** 와일드카드는 보안 노출 범위가 지나치게 넓습니다

현재 /api/v1/oauth/**ANY_METHOD에 추가되어 해당 경로 하위의 모든 엔드포인트를 인증 없이 공개합니다. 현재 노출되어야 하는 엔드포인트가 /api/v1/oauth/reissue/api/v1/oauth/logout 뿐이라면, 와일드카드 대신 구체적인 경로를 나열하는 것이 더 안전합니다. 향후 /api/v1/oauth/ 하위에 인증이 필요한 엔드포인트가 추가될 경우, 이 와일드카드에 의해 의도치 않게 공개될 위험이 있습니다.

🛡️ 더 좁은 경로로 수정 제안
-        "/api/v1/oauth/**",
+        "/api/v1/oauth/reissue",
+        "/api/v1/oauth/logout",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/com/bbangle/bbangle/config/security/PublicApiPath.java` at line
9, The "/api/v1/oauth/**" wildcard in PublicApiPath (the list used for
ANY_METHOD public endpoints) is too broad; replace the wildcard entry with the
specific endpoints that should be public (e.g., "/api/v1/oauth/reissue" and
"/api/v1/oauth/logout") by editing the collection/array in PublicApiPath where
"/api/v1/oauth/**" appears so only those explicit paths are exposed without
authentication. Ensure you update the constant/list used by the security
configuration (the ANY_METHOD public endpoints) to remove the wildcard and add
the two explicit paths.
src/main/java/com/bbangle/bbangle/auth/seller/controller/SellerOauthController.java (1)

39-40: 🛠️ Refactor suggestion | 🟠 Major

Duration.ofDays(14)OAuthService.REFRESH_TOKEN_DURATION과 중복되며, 다른 컨트롤러에서도 같은 문제가 있습니다.

OAuthService에 이미 REFRESH_TOKEN_DURATION 상수가 정의되어 있으므로, SellerOauthControllerOAuthController에서 이 상수를 참조하면 유지보수 시 한 곳만 수정하면 됩니다. 현재 세 개의 서비스(OAuthService, AdminAuthService, CustomerOauthService)에서 같은 값으로 중복 정의되어 있으므로, 중앙 집중식 상수로 통합하는 것을 권장합니다.

SellerOauthController 수정안
+import static com.bbangle.bbangle.auth.oauth.client.service.OAuthService.REFRESH_TOKEN_DURATION;
 ...
-        response.addHeader(HttpHeaders.SET_COOKIE, createCookie(dto.refreshToken(), Duration.ofDays(14)).toString());
+        response.addHeader(HttpHeaders.SET_COOKIE, createCookie(dto.refreshToken(), REFRESH_TOKEN_DURATION).toString());
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/com/bbangle/bbangle/auth/seller/controller/SellerOauthController.java`
around lines 39 - 40, 응답 쿠키에 하드코딩된 Duration.ofDays(14)이 여러 컨트롤러에 중복되어 있으므로
SellerOauthController와 OAuthController(및 AdminAuthService, CustomerOauthService에
있는 중복 정의)를 OAuthService에 정의된 REFRESH_TOKEN_DURATION 상수를 참조하도록 변경하세요; 즉,
createCookie(dto.refreshToken(), Duration.ofDays(14)) 호출들을
createCookie(dto.refreshToken(), OAuthService.REFRESH_TOKEN_DURATION)로 바꾸고, 중복으로
정의된 상수들은 제거하거나 중앙상수로 통합하여 한 곳(OAuthService)에만 유지되게 하십시오.
🧹 Nitpick comments (6)
src/main/java/com/bbangle/bbangle/util/CookieUtils.java (2)

14-15: secure(true) 를 로컬에서 수동으로 주석 처리해야 하는 TODO는 유지보수 위험 요소입니다

개발자가 주석 처리를 잊거나 실수로 secure=false인 상태로 배포할 수 있습니다. Spring의 프로파일 기반 설정으로 관리하는 방식을 권장합니다.

♻️ 프로파일 기반 secure 플래그 적용 예시
-public class CookieUtils {
+public class CookieUtils {
+
+    private CookieUtils() {}

-    public static ResponseCookie createCookie(String value, Duration duration) {
+    public static ResponseCookie createCookie(String value, Duration duration, boolean secure) {
         return ResponseCookie.from("refreshToken", value)
             .httpOnly(true)
-            // TODO : 로컬에서 사용할 때는 주석처리
-            .secure(true)
+            .secure(secure)
             .path("/")
             .maxAge(duration)
             .sameSite("Strict")
             .build();
     }

호출부 (예: OAuthController)에서는 @Value("${server.ssl.enabled:true}") 등으로 주입받아 사용:

CookieUtils.createCookie(value, duration, secureEnabled);
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/com/bbangle/bbangle/util/CookieUtils.java` around lines 14 -
15, The TODO to manually comment out .secure(true) is unsafe; change CookieUtils
to drive the cookie secure flag from a Spring property instead of hardcoding it:
add a configurable boolean (e.g., server.ssl.enabled or custom cookie.secure)
injected into the component or passed into CookieUtils.createCookie, then
replace the hardcoded .secure(true) with that property (use a default of true
for production). Update callers (e.g., OAuthController) to pass the injected
secure flag (or let CookieUtils read Environment/@Value) so local/dev profiles
can override to false while prod remains true.

9-9: 유틸리티 클래스에 private 생성자 추가 필요

CookieFixture.java는 올바르게 private 생성자를 갖추었지만 CookieUtils는 그렇지 않아 인스턴스 생성이 가능합니다.

♻️ 수정 제안
 public class CookieUtils {
+
+    private CookieUtils() {}
+
     public static ResponseCookie createCookie(String value, Duration duration) {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/com/bbangle/bbangle/util/CookieUtils.java` at line 9,
CookieUtils currently lacks a private constructor so it can be instantiated; add
a private no-arg constructor to the CookieUtils class (similar to CookieFixture)
to prevent instantiation — implement a private CookieUtils() { /* optional:
throw new AssertionError("no instances"); */ } inside the CookieUtils class
body.
src/main/java/com/bbangle/bbangle/config/security/auth/CustomOAuth2AuthorizationRequestResolver.java (1)

19-21: OAuth 경로 문자열 상수화 고려

"/api/v1/oauth/authorization" 이 현재 CustomOAuth2AuthorizationRequestResolver(Line 20), OAuth2SecurityConfig(Line 40), OAuth2ClientValidationFilter(부분 경로 /oauth/authorization/) 세 곳에 분산되어 하드코딩되어 있습니다. 경로가 변경될 경우 세 파일을 모두 수정해야 합니다.

OAuthApiPath 같은 상수 클래스를 추가하고 공통 상수로 관리하는 방안을 고려해 주세요.

♻️ 상수 추출 예시

새 상수 클래스 (예시):

// src/main/java/com/bbangle/bbangle/config/security/OAuthApiPath.java
public class OAuthApiPath {
    public static final String AUTHORIZATION_BASE = "/api/v1/oauth/authorization";
}

CustomOAuth2AuthorizationRequestResolver.java:

-            clientRegistrationRepository, "/api/v1/oauth/authorization"
+            clientRegistrationRepository, OAuthApiPath.AUTHORIZATION_BASE

OAuth2SecurityConfig.java:

-            "/api/v1/oauth/authorization/**",
+            OAuthApiPath.AUTHORIZATION_BASE + "/**",
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/com/bbangle/bbangle/config/security/auth/CustomOAuth2AuthorizationRequestResolver.java`
around lines 19 - 21, The OAuth authorization path string is hardcoded in
multiple places (CustomOAuth2AuthorizationRequestResolver, OAuth2SecurityConfig,
OAuth2ClientValidationFilter); extract it into a shared constant class (e.g.,
create OAuthApiPath with public static final String AUTHORIZATION_BASE) and
replace literal "/api/v1/oauth/authorization" occurrences with
OAuthApiPath.AUTHORIZATION_BASE in CustomOAuth2AuthorizationRequestResolver (the
DefaultOAuth2AuthorizationRequestResolver constructor call),
OAuth2SecurityConfig (where the same path is used), and
OAuth2ClientValidationFilter (where the partial path is checked), ensuring
imports and references are updated accordingly.
src/main/java/com/bbangle/bbangle/auth/oauth/client/service/OAuthService.java (1)

26-43: 신규 생성 경로에서 token.update(refreshToken) 호출이 불필요합니다.

RefreshToken.create(userId, role, refreshToken)로 이미 토큰 값이 설정된 상태에서 Line 38의 update는 같은 값을 다시 설정합니다. 기존 토큰 업데이트 경로에서만 필요한 호출입니다.

두 경로를 명시적으로 분리하면 의도가 더 명확해집니다:

제안된 수정
     `@Transactional`
     public String generateRefreshToken(Long userId, Role role) {
         String refreshToken = tokenProvider.generateToken(userId, role, REFRESH_TOKEN_DURATION);
 
-        RefreshToken token = refreshTokenRepository
+        refreshTokenRepository
             .findByUserIdAndUserRole(userId, role)
-            .orElseGet(() -> RefreshToken.create(
-                userId,
-                role,
-                refreshToken
-            ));
-
-        token.update(refreshToken);
-
-        refreshTokenRepository.save(token);
+            .ifPresentOrElse(
+                existing -> {
+                    existing.update(refreshToken);
+                    refreshTokenRepository.save(existing);
+                },
+                () -> refreshTokenRepository.save(
+                    RefreshToken.create(userId, role, refreshToken)
+                )
+            );
 
         return refreshToken;
     }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/com/bbangle/bbangle/auth/oauth/client/service/OAuthService.java`
around lines 26 - 43, The generateRefreshToken method currently always calls
token.update(refreshToken) even when a new RefreshToken was just created (via
RefreshToken.create), causing a redundant assignment; change the logic so you
fetch with refreshTokenRepository.findByUserIdAndUserRole(userId, role) and
ifPresent call token.update(refreshToken) then save, otherwise create a new
RefreshToken with RefreshToken.create(userId, role, refreshToken) and save it
without calling update — i.e., separate the "existing token" and "new token"
branches so token.update(...) is only invoked for existing tokens.
src/test/java/com/bbangle/bbangle/auth/oauth/client/service/OAuthServiceUnitTest.java (1)

104-115: existToken 테스트에서 mock 매처와 테스트 데이터 불일치.

Line 111에서 findByRefreshToken(any())를 사용하고 있어, refreshToken 변수의 실제 값("validRefreshToken")과 무관하게 mock이 동작합니다. 실제 값을 매칭하도록 수정하면 테스트 의도가 더 명확해집니다.

제안된 수정
-            given(refreshTokenRepository.findByRefreshToken(any())).willReturn(Optional.of(existing));
+            given(refreshTokenRepository.findByRefreshToken(refreshToken)).willReturn(Optional.of(existing));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/test/java/com/bbangle/bbangle/auth/oauth/client/service/OAuthServiceUnitTest.java`
around lines 104 - 115, The test existToken should use a precise mock matcher
and aligned test data: change the repository stub to match the actual
refreshToken variable (use eq(refreshToken) with
given(refreshTokenRepository.findByRefreshToken(...))).willReturn(...)) and
ensure the RefreshToken created via RefreshToken.create(...) uses the same token
string as the refreshToken variable (replace "refreshToken" with
"validRefreshToken") so the mocked findByRefreshToken and test data are
consistent; update references in the test method existToken that call
findByRefreshToken and RefreshToken.create accordingly.
src/main/java/com/bbangle/bbangle/auth/oauth/client/controller/OAuthController.java (1)

69-69: 쿠키 삭제 시 Duration.ZERO 사용 권장

Duration.ofMillis(1)Max-Age로 변환 시 0초로 잘려 쿠키를 삭제하는 효과를 냅니다. 의도를 명확히 하려면 Duration.ZERO를 사용하는 것이 좋습니다.

♻️ 제안 수정
-        response.addHeader(HttpHeaders.SET_COOKIE, createCookie("", Duration.ofMillis(1)).toString());
+        response.addHeader(HttpHeaders.SET_COOKIE, createCookie("", Duration.ZERO).toString());
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/com/bbangle/bbangle/auth/oauth/client/controller/OAuthController.java`
at line 69, The response currently sets a deletion cookie using
Duration.ofMillis(1) which is ambiguous; update the call in OAuthController
where response.addHeader(HttpHeaders.SET_COOKIE, createCookie("",
Duration.ofMillis(1)).toString()) to use Duration.ZERO instead (i.e., call
createCookie("", Duration.ZERO)) so the intent to delete the cookie is explicit;
ensure the change is made where createCookie and HttpHeaders.SET_COOKIE are used
together in that controller.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/main/java/com/bbangle/bbangle/auth/oauth/client/facade/OAuthFacade.java`:
- Around line 17-31: 현재 reissueToken 메서드에서 oAuthService.deleteRefreshToken(...)
호출 후 새로운 토큰 생성(generateRefreshToken, generateAccessToken) 도중 실패하면 기존 토큰이 삭제되어 토큰
유실이 발생할 수 있으므로 reissueToken 메서드에 트랜잭션 경계를 추가하세요: reissueToken 메서드에
`@Transactional` 애너테이션을 적용해 tokenProvider.parseRefreshToken,
oAuthService.refreshTokenValidate, oAuthService.deleteRefreshToken,
oAuthService.generateRefreshToken 및 oAuthService.generateAccessToken 호출이 하나의 원자적
트랜잭션으로 실행되도록 하고, 필요한 경우 트랜잭션 전파 정책(예: REQUIRED)과 롤백 대상(예: Exception)을 설정하세요.

In
`@src/test/java/com/bbangle/bbangle/auth/oauth/client/controller/OAuthControllerTest.java`:
- Line 97: Update the outdated comment in OAuthControllerTest: replace the old
class name "OAuth2SellerFacade" with the current "OAuthFacade" (the line that
currently reads "// 쿠키가 없을 경우 OAuth2SellerFacade는 호출조차 하지 않음"). Ensure any other
nearby comments in OAuthControllerTest that reference OAuth2SellerFacade are
similarly updated to OAuthFacade so comments match the refactored code.
- Around line 117-130: The test in OAuthControllerTest.logout currently asserts
cookie expiration and response body but doesn't verify the controller called
oAuthService.deleteRefreshToken; after the mockMvc.perform(...) assertions add a
Mockito verification that oAuthService.deleteRefreshToken was invoked once with
the refresh token from CookieFixture.defaultCookie() (e.g.
then(oAuthService).should(times(1)).deleteRefreshToken("refreshToken") or the
exact token value returned by CookieFixture.defaultCookie()), so the server-side
token invalidation is asserted.

---

Outside diff comments:
In
`@src/main/java/com/bbangle/bbangle/auth/seller/controller/SellerOauthController.java`:
- Around line 39-40: 응답 쿠키에 하드코딩된 Duration.ofDays(14)이 여러 컨트롤러에 중복되어 있으므로
SellerOauthController와 OAuthController(및 AdminAuthService, CustomerOauthService에
있는 중복 정의)를 OAuthService에 정의된 REFRESH_TOKEN_DURATION 상수를 참조하도록 변경하세요; 즉,
createCookie(dto.refreshToken(), Duration.ofDays(14)) 호출들을
createCookie(dto.refreshToken(), OAuthService.REFRESH_TOKEN_DURATION)로 바꾸고, 중복으로
정의된 상수들은 제거하거나 중앙상수로 통합하여 한 곳(OAuthService)에만 유지되게 하십시오.

In `@src/main/java/com/bbangle/bbangle/config/security/PublicApiPath.java`:
- Line 9: The "/api/v1/oauth/**" wildcard in PublicApiPath (the list used for
ANY_METHOD public endpoints) is too broad; replace the wildcard entry with the
specific endpoints that should be public (e.g., "/api/v1/oauth/reissue" and
"/api/v1/oauth/logout") by editing the collection/array in PublicApiPath where
"/api/v1/oauth/**" appears so only those explicit paths are exposed without
authentication. Ensure you update the constant/list used by the security
configuration (the ANY_METHOD public endpoints) to remove the wildcard and add
the two explicit paths.

---

Nitpick comments:
In
`@src/main/java/com/bbangle/bbangle/auth/oauth/client/controller/OAuthController.java`:
- Line 69: The response currently sets a deletion cookie using
Duration.ofMillis(1) which is ambiguous; update the call in OAuthController
where response.addHeader(HttpHeaders.SET_COOKIE, createCookie("",
Duration.ofMillis(1)).toString()) to use Duration.ZERO instead (i.e., call
createCookie("", Duration.ZERO)) so the intent to delete the cookie is explicit;
ensure the change is made where createCookie and HttpHeaders.SET_COOKIE are used
together in that controller.

In
`@src/main/java/com/bbangle/bbangle/auth/oauth/client/service/OAuthService.java`:
- Around line 26-43: The generateRefreshToken method currently always calls
token.update(refreshToken) even when a new RefreshToken was just created (via
RefreshToken.create), causing a redundant assignment; change the logic so you
fetch with refreshTokenRepository.findByUserIdAndUserRole(userId, role) and
ifPresent call token.update(refreshToken) then save, otherwise create a new
RefreshToken with RefreshToken.create(userId, role, refreshToken) and save it
without calling update — i.e., separate the "existing token" and "new token"
branches so token.update(...) is only invoked for existing tokens.

In
`@src/main/java/com/bbangle/bbangle/config/security/auth/CustomOAuth2AuthorizationRequestResolver.java`:
- Around line 19-21: The OAuth authorization path string is hardcoded in
multiple places (CustomOAuth2AuthorizationRequestResolver, OAuth2SecurityConfig,
OAuth2ClientValidationFilter); extract it into a shared constant class (e.g.,
create OAuthApiPath with public static final String AUTHORIZATION_BASE) and
replace literal "/api/v1/oauth/authorization" occurrences with
OAuthApiPath.AUTHORIZATION_BASE in CustomOAuth2AuthorizationRequestResolver (the
DefaultOAuth2AuthorizationRequestResolver constructor call),
OAuth2SecurityConfig (where the same path is used), and
OAuth2ClientValidationFilter (where the partial path is checked), ensuring
imports and references are updated accordingly.

In `@src/main/java/com/bbangle/bbangle/util/CookieUtils.java`:
- Around line 14-15: The TODO to manually comment out .secure(true) is unsafe;
change CookieUtils to drive the cookie secure flag from a Spring property
instead of hardcoding it: add a configurable boolean (e.g., server.ssl.enabled
or custom cookie.secure) injected into the component or passed into
CookieUtils.createCookie, then replace the hardcoded .secure(true) with that
property (use a default of true for production). Update callers (e.g.,
OAuthController) to pass the injected secure flag (or let CookieUtils read
Environment/@Value) so local/dev profiles can override to false while prod
remains true.
- Line 9: CookieUtils currently lacks a private constructor so it can be
instantiated; add a private no-arg constructor to the CookieUtils class (similar
to CookieFixture) to prevent instantiation — implement a private CookieUtils() {
/* optional: throw new AssertionError("no instances"); */ } inside the
CookieUtils class body.

In
`@src/test/java/com/bbangle/bbangle/auth/oauth/client/service/OAuthServiceUnitTest.java`:
- Around line 104-115: The test existToken should use a precise mock matcher and
aligned test data: change the repository stub to match the actual refreshToken
variable (use eq(refreshToken) with
given(refreshTokenRepository.findByRefreshToken(...))).willReturn(...)) and
ensure the RefreshToken created via RefreshToken.create(...) uses the same token
string as the refreshToken variable (replace "refreshToken" with
"validRefreshToken") so the mocked findByRefreshToken and test data are
consistent; update references in the test method existToken that call
findByRefreshToken and RefreshToken.create accordingly.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 332b1ae and a868e4c.

📒 Files selected for processing (26)
  • src/main/java/com/bbangle/bbangle/auth/oauth/client/controller/OAuthController.java
  • src/main/java/com/bbangle/bbangle/auth/oauth/client/controller/swagger/OAuthApi.java
  • src/main/java/com/bbangle/bbangle/auth/oauth/client/facade/OAuthFacade.java
  • src/main/java/com/bbangle/bbangle/auth/oauth/client/service/OAuthService.java
  • src/main/java/com/bbangle/bbangle/auth/seller/controller/SellerOauthController.java
  • src/main/java/com/bbangle/bbangle/auth/seller/controller/swagger/SellerOauthApi.java
  • src/main/java/com/bbangle/bbangle/auth/seller/facade/OAuth2SellerFacade.java
  • src/main/java/com/bbangle/bbangle/auth/seller/service/OAuthSellerService.java
  • src/main/java/com/bbangle/bbangle/config/security/OAuth2SecurityConfig.java
  • src/main/java/com/bbangle/bbangle/config/security/PublicApiPath.java
  • src/main/java/com/bbangle/bbangle/config/security/auth/CustomOAuth2AuthorizationRequestResolver.java
  • src/main/java/com/bbangle/bbangle/config/security/auth/OAuth2ClientValidationFilter.java
  • src/main/java/com/bbangle/bbangle/util/CookieUtils.java
  • src/test/java/com/bbangle/bbangle/auth/oauth/client/controller/OAuthControllerTest.java
  • src/test/java/com/bbangle/bbangle/auth/oauth/client/facade/OAuthFacadeIntegrationTest.java
  • src/test/java/com/bbangle/bbangle/auth/oauth/client/facade/OAuthFacadeUnitTest.java
  • src/test/java/com/bbangle/bbangle/auth/oauth/client/service/OAuthServiceIntegrationTest.java
  • src/test/java/com/bbangle/bbangle/auth/oauth/client/service/OAuthServiceUnitTest.java
  • src/test/java/com/bbangle/bbangle/auth/seller/controller/SellerOauthControllerTest.java
  • src/test/java/com/bbangle/bbangle/auth/seller/facade/OAuth2SellerFacadeIntegrationTest.java
  • src/test/java/com/bbangle/bbangle/auth/seller/facade/OAuth2SellerFacadeUnitTest.java
  • src/test/java/com/bbangle/bbangle/auth/seller/service/OAuthSellerServiceIntegrationTest.java
  • src/test/java/com/bbangle/bbangle/auth/seller/service/OAuthSellerServiceUnitTest.java
  • src/test/java/com/bbangle/bbangle/claim/repository/ClaimRepositoryDataJpaTest.java
  • src/test/java/com/bbangle/bbangle/config/security/auth/OAuth2ClientValidationFilterUnitTest.java
  • src/test/java/com/bbangle/bbangle/fixture/oauth/CookieFixture.java
💤 Files with no reviewable changes (7)
  • src/main/java/com/bbangle/bbangle/auth/seller/controller/swagger/SellerOauthApi.java
  • src/test/java/com/bbangle/bbangle/claim/repository/ClaimRepositoryDataJpaTest.java
  • src/test/java/com/bbangle/bbangle/auth/seller/service/OAuthSellerServiceIntegrationTest.java
  • src/main/java/com/bbangle/bbangle/auth/seller/service/OAuthSellerService.java
  • src/test/java/com/bbangle/bbangle/auth/seller/controller/SellerOauthControllerTest.java
  • src/test/java/com/bbangle/bbangle/auth/seller/service/OAuthSellerServiceUnitTest.java
  • src/test/java/com/bbangle/bbangle/auth/seller/facade/OAuth2SellerFacadeIntegrationTest.java

- CookieUtils 주석 삭제
- OAuth API URI를 상수로 변경
- Refresh Token 발급 로직 리팩토링
Copy link

@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: 1

🧹 Nitpick comments (1)
src/main/java/com/bbangle/bbangle/auth/oauth/client/controller/OAuthController.java (1)

57-57: 쿠키 유효 기간을 OAuthService.REFRESH_TOKEN_DURATION 상수로 교체하세요.

Duration.ofDays(14)가 하드코딩되어 있지만, 이미 OAuthService.REFRESH_TOKEN_DURATION으로 동일한 값이 상수로 정의되어 있습니다. 추후 유효 기간이 변경될 경우 이 코드가 함께 갱신되지 않을 수 있습니다.

♻️ 제안된 수정
-        response.addHeader(HttpHeaders.SET_COOKIE, createCookie(dto.refreshToken(), Duration.ofDays(14)).toString());
+        response.addHeader(HttpHeaders.SET_COOKIE, createCookie(dto.refreshToken(), OAuthService.REFRESH_TOKEN_DURATION).toString());

참고: SellerOauthController.java(line 38)에서도 동일하게 Duration.ofDays(14)가 하드코딩되어 있으므로 함께 수정하는 것을 권장합니다.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/com/bbangle/bbangle/auth/oauth/client/controller/OAuthController.java`
at line 57, Replace the hardcoded Duration.ofDays(14) used when creating the
refresh-token cookie with the shared constant
OAuthService.REFRESH_TOKEN_DURATION; specifically update the call in
OAuthController where response.addHeader(... createCookie(dto.refreshToken(),
Duration.ofDays(14)) ...) to use createCookie(dto.refreshToken(),
OAuthService.REFRESH_TOKEN_DURATION) and make the same change in
SellerOauthController to ensure both controllers rely on the single source of
truth.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/test/java/com/bbangle/bbangle/auth/oauth/client/service/OAuthServiceUnitTest.java`:
- Around line 60-77: The test success_update currently omits verifying that the
repository persists the updated token; update the unit test to assert that
RefreshTokenRepository.save(...) is called when
OAuthService.generateRefreshToken(...) finds an existing RefreshToken (created
via RefreshToken.create(...) and updated via existing.update(...));
specifically, after calling service.generateRefreshToken(1L, Role.ROLE_SELLER)
add a verify(refreshTokenRepository).save(...) (or equivalent with any() /
argThat for the RefreshToken) to ensure the update path in
OAuthService.generateRefreshToken actually invokes refreshTokenRepository.save
and would catch persistence bugs for non-JPA stores.

---

Nitpick comments:
In
`@src/main/java/com/bbangle/bbangle/auth/oauth/client/controller/OAuthController.java`:
- Line 57: Replace the hardcoded Duration.ofDays(14) used when creating the
refresh-token cookie with the shared constant
OAuthService.REFRESH_TOKEN_DURATION; specifically update the call in
OAuthController where response.addHeader(... createCookie(dto.refreshToken(),
Duration.ofDays(14)) ...) to use createCookie(dto.refreshToken(),
OAuthService.REFRESH_TOKEN_DURATION) and make the same change in
SellerOauthController to ensure both controllers rely on the single source of
truth.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a868e4c and 955c344.

📒 Files selected for processing (9)
  • src/main/java/com/bbangle/bbangle/auth/oauth/client/controller/OAuthController.java
  • src/main/java/com/bbangle/bbangle/auth/oauth/client/service/OAuthService.java
  • src/main/java/com/bbangle/bbangle/config/security/PublicApiPath.java
  • src/main/java/com/bbangle/bbangle/config/security/auth/CustomOAuth2AuthorizationRequestResolver.java
  • src/main/java/com/bbangle/bbangle/config/security/auth/OAuth2ClientValidationFilter.java
  • src/main/java/com/bbangle/bbangle/util/CookieUtils.java
  • src/test/java/com/bbangle/bbangle/auth/oauth/client/controller/OAuthControllerTest.java
  • src/test/java/com/bbangle/bbangle/auth/oauth/client/service/OAuthServiceUnitTest.java
  • src/test/java/com/bbangle/bbangle/config/security/auth/OAuth2ClientValidationFilterUnitTest.java
🚧 Files skipped from review as they are similar to previous changes (3)
  • src/main/java/com/bbangle/bbangle/util/CookieUtils.java
  • src/main/java/com/bbangle/bbangle/config/security/auth/CustomOAuth2AuthorizationRequestResolver.java
  • src/main/java/com/bbangle/bbangle/config/security/PublicApiPath.java

- Token 유효 기간을 상수로 변경
Copy link

@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: 1

🧹 Nitpick comments (1)
src/main/java/com/bbangle/bbangle/auth/oauth/client/controller/OAuthController.java (1)

32-32: @RequestMapping("") 제거 권장

클래스 레벨의 @RequestMapping("")은 각 메서드가 이미 절대 경로를 직접 지정하고 있어 아무런 효과가 없습니다. 불필요한 노이즈를 줄이기 위해 제거하거나 아예 생략하는 것이 더 명확합니다.

♻️ Proposed fix
 `@RequiredArgsConstructor`
 `@RestController`
-@RequestMapping("")
 public class OAuthController implements OAuthApi {
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@src/main/java/com/bbangle/bbangle/auth/oauth/client/controller/OAuthController.java`
at line 32, Remove the no-op class-level annotation `@RequestMapping`("") from the
OAuthController class (symbol: OAuthController) since individual handler methods
already declare absolute paths; delete the annotation from the class declaration
and remove the unused import
org.springframework.web.bind.annotation.RequestMapping if it becomes unused to
avoid dead imports and keep the controller clean.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@src/main/java/com/bbangle/bbangle/auth/oauth/client/controller/OAuthController.java`:
- Around line 41-45: OAuthController의 login 구현에서 Spring이 인터페이스(`@OAuthApi`) 메서드의
어노테이션을 상속하지 못하므로 UserType과 ProfileType 파라미터에 명시적으로 `@RequestParam을` 추가하십시오:
login(OauthServerType oauthServerType, `@RequestParam`("user") UserType userType,
`@RequestParam`(value="profile", required=false, defaultValue="prod") ProfileType
profileType). 이렇게 해서 OAuthController.login, UserType, ProfileType 시그니처가
OAuthApi의 기대와 일치하도록 만드세요.

---

Nitpick comments:
In
`@src/main/java/com/bbangle/bbangle/auth/oauth/client/controller/OAuthController.java`:
- Line 32: Remove the no-op class-level annotation `@RequestMapping`("") from the
OAuthController class (symbol: OAuthController) since individual handler methods
already declare absolute paths; delete the annotation from the class declaration
and remove the unused import
org.springframework.web.bind.annotation.RequestMapping if it becomes unused to
avoid dead imports and keep the controller clean.

ℹ️ Review info

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 955c344 and aca59c5.

📒 Files selected for processing (4)
  • src/main/java/com/bbangle/bbangle/auth/oauth/client/controller/OAuthController.java
  • src/main/java/com/bbangle/bbangle/auth/oauth/client/service/OAuthService.java
  • src/main/java/com/bbangle/bbangle/auth/seller/controller/SellerOauthController.java
  • src/main/java/com/bbangle/bbangle/config/security/jwt/TokenProvider.java
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/bbangle/bbangle/auth/oauth/client/service/OAuthService.java

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Refactor] OAuth2 API URL 변경

1 participant