Skip to content

[Feat]#7 authentication - #8

Merged
Sehi55 merged 7 commits into
devfrom
feat/7-authentication
Apr 30, 2026
Merged

Sehi55 merged 7 commits into
devfrom
feat/7-authentication

Conversation

@Sehi55

@Sehi55 Sehi55 commented Apr 29, 2026

Copy link
Copy Markdown
Contributor

📝 작업 내용

이번 PR에서 작업한 내용을 설명해주세요.

🚀 주요 변경 사항

완료한 이슈 번호
Close #7
관련된 이슈 번호 (닫고 싶지 않은 경우)
Related to #

✅ 자체 체크리스트 (필수)

  • ./gradlew build 실행 결과 정상 (인증샷 첨부)
image

📸 테스트 인증샷

빌드 결과 및 Postman 실행 화면을 여기에 첨부해 주세요.

💬 리뷰어 전달사항 (선택)

특별히 봐주었으면 하는 부분이나 논의가 필요한 점을 적어주세요.

  • 논의점


📎 참고 자료

관련 문서, 레퍼런스 링크 등이 있다면 여기에 첨부해주세요.

Summary by CodeRabbit

릴리스 노트

  • New Features

    • JWT 기반 인증 및 OAuth2 리소스 서버 연동 추가
    • CORS 설정 지원 추가 (허용 출처 구성 가능)
  • Improvements

    • 환경 변수 기반 구성 지원으로 배포 유연성 향상
    • 인증·권한 정책 적용으로 관리·관리자 엔드포인트 접근 제어 강화
    • 게이트웨이 라우팅에 인증 관련 경로 전달 범위 확장

@Sehi55 Sehi55 self-assigned this Apr 29, 2026
@Sehi55 Sehi55 added the enhancement New feature or request label Apr 29, 2026
@Sehi55 Sehi55 linked an issue Apr 29, 2026 that may be closed by this pull request
2 tasks
@coderabbitai

coderabbitai Bot commented Apr 29, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: d599f84e-eed8-4803-93a9-8248a4ed5fd8

📥 Commits

Reviewing files that changed from the base of the PR and between 46d353b and 0d18656.

📒 Files selected for processing (2)
  • src/main/java/com/michelet/gateway/infrastructure/security/JwtAuthenticationFilter.java
  • src/main/resources/application.yml
🚧 Files skipped from review as they are similar to previous changes (2)
  • src/main/resources/application.yml
  • src/main/java/com/michelet/gateway/infrastructure/security/JwtAuthenticationFilter.java

📝 Walkthrough

Walkthrough

Spring Cloud Gateway에 대한 JWT 기반 인증과 CORS 구성이 추가되었습니다. Spring Security, JWT 디코더 및 권한 변환기, 글로벌 인증 필터가 도입되고 애플리케이션 환경 설정과 빌드 의존성이 업데이트되었습니다.

Changes

Cohort / File(s) Summary
빌드 의존성
build.gradle
JWT 라이브러리 및 Spring Security/OAuth2 리소스 서버 의존성 추가, 테스트에 spring-security-test 포함.
CORS 구성
src/main/java/com/michelet/gateway/infrastructure/config/CorsConfig.java, src/main/java/com/michelet/gateway/infrastructure/config/CorsProperties.java
CORS 프로퍼티 레코드와 CorsWebFilter 빈 추가 — 허용 출처 바인딩, HTTP 메서드/헤더/자격증명 설정.
보안 설정 및 JWT 처리
src/main/java/com/michelet/gateway/infrastructure/config/SecurityConfig.java
WebFlux용 SecurityWebFilterChain 추가, CSRF 비활성화, 인증 제외 및 권한 기반 경로 제어, ReactiveJwtDecoder(HMAC-SHA256) 빈 등록.
권한 변환기
src/main/java/com/michelet/gateway/infrastructure/security/GatewayRoleConverter.java
JWT의 role 클레임을 읽어 GrantedAuthority 스트림으로 변환하는 Converter 구현.
글로벌 인증 필터
src/main/java/com/michelet/gateway/infrastructure/security/JwtAuthenticationFilter.java
ReactiveSecurityContext에서 인증을 확인해 JWT일 경우 요청 헤더(X-User-Id, X-User-Role)를 제거/설정하며 요청을 변형하는 GlobalFilter 구현(정렬 우선순위 지정).
애플리케이션 설정
src/main/resources/application.yml, src/main/resources/application-local.yml, src/main/resources/application-test.yml, src/main/resources/application-docker.yml
JWT 시크릿 및 CORS 허용 출처 설정 추가/조정, Eureka defaultZone에 환경변수 템플릿 적용, 인증 관련 라우트 경로 확장.
버전 관리 설정
.gitignore
.env 추가 및 /.vscode/ 복원(개행 포함).

Sequence Diagram(s)

sequenceDiagram
    actor Client
    participant Gateway as Spring Cloud Gateway
    participant SecurityChain as Security Filter Chain
    participant RoleConv as GatewayRoleConverter
    participant JwtFilter as JwtAuthenticationFilter
    participant Service as Downstream Service

    Client->>Gateway: HTTP Request (with/without Authorization)
    Gateway->>SecurityChain: Apply SecurityWebFilterChain
    SecurityChain->>SecurityChain: Decode & Validate JWT (ReactiveJwtDecoder)
    SecurityChain->>RoleConv: Convert JWT -> Authorities
    RoleConv-->>SecurityChain: GrantedAuthority
    SecurityChain-->>JwtFilter: Authentication present (JwtAuthenticationToken)
    JwtFilter->>JwtFilter: Extract subject and role claim
    JwtFilter->>Gateway: Mutate Request Headers (X-User-Id, X-User-Role)
    Gateway->>Service: Forward Mutated Request
    Service-->>Client: Response
Loading
sequenceDiagram
    actor User
    participant ClientApp as Client App
    participant Gateway as API Gateway
    participant AuthSvc as Auth Service
    participant JwtDecoder as JWT Generator/Decoder

    User->>ClientApp: Submit credentials
    ClientApp->>Gateway: POST /api/v1/auth/login
    Gateway->>AuthSvc: Route to Auth Service
    AuthSvc->>JwtDecoder: Generate signed JWT (role claim)
    JwtDecoder-->>AuthSvc: JWT Token
    AuthSvc-->>ClientApp: Return JWT
    ClientApp->>Gateway: Subsequent requests with Authorization
    Gateway->>JwtDecoder: Verify / Decode JWT
    JwtDecoder-->>Gateway: Claims (sub, role)
    Gateway->>ClientApp: Authenticated response / proxied request
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 토끼가 전하는 작은 축하
새벽에 토큰이 반짝이고,
역할은 "ROLE_"로 단장했어요.
헤더를 살며시 정리해 건네니,
서비스들 사이에 바람이 통하네요. 🥕✨

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning The PR implements JWT-based authentication with security configuration, role converter, and authentication filter. However, Redis whitelist refresh token storage requirement from issue #7 is not evident in the code changes. Implement Redis-based whitelist refresh token storage as specified in issue #7 checklist to fully meet linked issue requirements.
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 (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title '[Feat]#7 authentication' is directly related to the main objective of implementing authentication functionality, clearly indicating the primary change.
Out of Scope Changes check ✅ Passed All changes are directly related to authentication implementation. CORS configuration, gateway route updates, and environment variable adjustments support the authentication feature scope.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/7-authentication

Review rate limit: 2/3 reviews remaining, refill in 20 minutes.

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

@github-actions
github-actions Bot requested a review from qldo April 29, 2026 20:08

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

🧹 Nitpick comments (1)
src/main/java/com/michelet/gateway/infrastructure/config/SecurityConfig.java (1)

42-47: jwt.secret에 대한 길이/유효성 검증을 빈 생성 시점에 추가해 주세요.

HS256 키가 너무 짧거나 비어 있으면 운영 중 토큰 검증 실패/보안 약화로 이어질 수 있어, 애플리케이션 시작 시 fail-fast 하는 편이 안전합니다.

🔧 제안 diff
 `@Bean`
 public ReactiveJwtDecoder reactiveJwtDecoder(`@Value`("${jwt.secret}") String secret){
+    byte[] secretBytes = secret == null ? new byte[0] : secret.getBytes(StandardCharsets.UTF_8);
+    if (secretBytes.length < 32) {
+        throw new IllegalStateException("jwt.secret must be at least 32 bytes for HS256");
+    }
     SecretKey secretKey = new SecretKeySpec(
-            secret.getBytes(StandardCharsets.UTF_8),
+            secretBytes,
             "HmacSHA256"
     );
     return NimbusReactiveJwtDecoder.withSecretKey(secretKey).build();
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/main/java/com/michelet/gateway/infrastructure/config/SecurityConfig.java`
around lines 42 - 47, Check and validate the jwt.secret value inside the
reactiveJwtDecoder bean factory: ensure it's non-empty and meets a minimum
entropy/length (e.g., at least 32 characters/bytes) before constructing the
SecretKey (SecretKey secretKey = new SecretKeySpec(...)); if validation fails,
throw an unchecked exception (e.g., IllegalArgumentException) so the application
fails fast during startup and does not build the NimbusReactiveJwtDecoder.
🤖 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/michelet/gateway/infrastructure/security/JwtAuthenticationFilter.java`:
- Around line 39-43: The request mutation in JwtAuthenticationFilter currently
uses normalize() which can turn null into an empty header and does not
explicitly remove existing headers; update the ServerHttpRequest mutation (the
exchange.getRequest().mutate() call that builds mutatedRequest) to first remove
any existing USER_ID_HEADER and USER_ROLE_HEADER values and then set each header
only when the JWT-derived value is non-null/non-empty (avoid normalize()
producing empty strings); reference the USER_ID_HEADER/USER_ROLE_HEADER
constants, the normalize(String) helper, and the mutatedRequest creation to
locate and change the logic so headers are explicitly removed and only added
when valid values exist.
- Around line 22-27: 현재 filter 메서드의 onErrorResume이 에러 발생 시 원본 요청으로
chain.filter(exchange)를 다시 호출해 비멱등 요청을 중복 처리하게 하므로, onErrorResume에서
chain.filter(exchange)를 재호출하지 말고 에러를 그대로 전파하거나 적절한 에러 응답을 반환하도록 변경하세요; 구체적으로
JwtAuthenticationFilter.filter 내부의 onErrorResume 대신 에러를 그대로 반환하는 Mono.error(ex)를
사용하거나 ServerWebExchange에 적절한 에러 상태(예: 4xx/5xx) 응답을 쓰고 Mono.empty/Mono<Void>로
마무리하여 addHeaders/chain.filter 재실행을 방지하세요.

In `@src/main/resources/application-docker.yml`:
- Line 4: defaultZone 설정이 환경변수가 없을 때 리터럴로 남아 Eureka 연결에 실패하므로
application-docker.yml의 defaultZone에 EUREKA_CONTAINER_NAME 및 EUREKA_PORT에 대한 안전한
기본값을 추가하거나 환경 변수 확장 문법을 사용해 기본값을 지정하세요; 예를 들어 defaultZone 항목에서 참조되는
EUREKA_CONTAINER_NAME, EUREKA_PORT 식별자를 찾아(application-local.yml의 설정을 참고) 안전한 기본
호스트명/포트로 대체하거나 ${VAR:default} 형식으로 기본값을 제공하도록 변경하면 됩니다.

In `@src/main/resources/application.yml`:
- Around line 65-69: 기본 프로파일과 각 환경 프로파일(application-local.yml,
application-docker.yml)에 jwt.secret이 빠져 있어 SecurityConfig의
`@Value`("${jwt.secret}") 주입 시 애플리케이션이 실패하므로, jwt.secret 값을 각 프로파일에 명시하거나 환경변수로
주입되도록 설정하세요(예: SecurityConfig가 기대하는 환경변수 이름 사용 또는 프로퍼티 기본값 제공). 또한
cors.allowed-origins가 비어 있어 CORS가 차단되니 기본 application.yml과 docker/local 프로파일에
cors.allowed-origins에 허용할 원본 목록을 명시하거나 환경변수로 주입되게 설정하여 SecurityConfig와 CORS 구성이
모두 정상 동작하도록 하세요.

---

Nitpick comments:
In
`@src/main/java/com/michelet/gateway/infrastructure/config/SecurityConfig.java`:
- Around line 42-47: Check and validate the jwt.secret value inside the
reactiveJwtDecoder bean factory: ensure it's non-empty and meets a minimum
entropy/length (e.g., at least 32 characters/bytes) before constructing the
SecretKey (SecretKey secretKey = new SecretKeySpec(...)); if validation fails,
throw an unchecked exception (e.g., IllegalArgumentException) so the application
fails fast during startup and does not build the NimbusReactiveJwtDecoder.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: b971c1e2-55f4-464c-842e-f8229eed0d27

📥 Commits

Reviewing files that changed from the base of the PR and between 13fbf34 and 46d353b.

📒 Files selected for processing (11)
  • .gitignore
  • build.gradle
  • src/main/java/com/michelet/gateway/infrastructure/config/CorsConfig.java
  • src/main/java/com/michelet/gateway/infrastructure/config/CorsProperties.java
  • src/main/java/com/michelet/gateway/infrastructure/config/SecurityConfig.java
  • src/main/java/com/michelet/gateway/infrastructure/security/GatewayRoleConverter.java
  • src/main/java/com/michelet/gateway/infrastructure/security/JwtAuthenticationFilter.java
  • src/main/resources/application-docker.yml
  • src/main/resources/application-local.yml
  • src/main/resources/application-test.yml
  • src/main/resources/application.yml

Comment thread src/main/resources/application-docker.yml
Comment thread src/main/resources/application.yml

@jihxonx jihxonx left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

확인했습니다!

@qldo qldo left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

확인하였습니다

@Jinyoung-Kim96 Jinyoung-Kim96 left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

확인했습니다

@Sehi55
Sehi55 merged commit ff4632f into dev Apr 30, 2026
3 checks passed
@Sehi55
Sehi55 deleted the feat/7-authentication branch April 30, 2026 03:23
@coderabbitai coderabbitai Bot mentioned this pull request May 16, 2026
Merged
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[FEAT] 인증 구현

4 participants