Skip to content

fix: JWT 인증 버그 수정 및 예외처리 HTTP 상태코드 통일 - #39

Merged
yoonjeonggg merged 1 commit into
mainfrom
refactor/jwt-auth-bug-and-http-status-fix
May 22, 2026
Merged

yoonjeonggg merged 1 commit into
mainfrom
refactor/jwt-auth-bug-and-http-status-fix

Conversation

@yoonjeonggg

@yoonjeonggg yoonjeonggg commented May 22, 2026 •

Copy link
Copy Markdown
Contributor

[치명적 버그]

  • JwtAuthenticationFilter가 Spring 내장 UserDetails를 principal로 설정해
    SecurityUtils.getCurrentUser()의 instanceof 체크 실패로
    JWT 인증 사용자 전원 401 반환되던 문제 수정
    → UserRepository에서 User 엔티티 직접 로드하도록 변경

[HTTP 상태코드 수정]

  • InvalidPasswordException: 400 BAD_REQUEST → 401 UNAUTHORIZED
  • CallService.joinCall(): 방 멤버 아닐 때 404 RoomMemberNotFoundException
    → 403 NotRoomMemberException으로 변경
  • RoomService.patchRoom/deleteRoom(): AccessDeniedException(COMMON_403)
    → NotRoomHostException(ROOM_007, 403)으로 도메인 예외 통일

Summary by CodeRabbit

  • Bug Fixes
    • Validation error messages now display specific field names instead of generic text.
    • Password authentication errors now return the correct HTTP status code (UNAUTHORIZED).
    • Access control errors properly distinguish between host-only and room-member-only operations with appropriate error messaging.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 22, 2026 •

Copy link
Copy Markdown

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 421b7ee6-341b-41d8-a2a8-65da1761a56e

📥 Commits

Reviewing files that changed from the base of the PR and between 250dd03 and 8058de8.

📒 Files selected for processing (13)
  • src/main/java/chainsawman/gesture/config/SecurityConfig.java
  • src/main/java/chainsawman/gesture/exceptions/room/NotRoomHostException.java
  • src/main/java/chainsawman/gesture/exceptions/user/InvalidPasswordException.java
  • src/main/java/chainsawman/gesture/global/ApiGlobalResponseHandler.java
  • src/main/java/chainsawman/gesture/security/JwtAuthenticationFilter.java
  • src/main/java/chainsawman/gesture/service/AuthService.java
  • src/main/java/chainsawman/gesture/service/CallService.java
  • src/main/java/chainsawman/gesture/service/MeetingService.java
  • src/main/java/chainsawman/gesture/service/RoomService.java
  • src/main/java/chainsawman/gesture/service/UserService.java
  • src/test/java/chainsawman/gesture/service/CallServiceTest.java
  • src/test/java/chainsawman/gesture/service/FriendServiceTest.java
  • src/test/java/chainsawman/gesture/service/MeetingServiceTest.java

📝 Walkthrough

Walkthrough

This PR refactors authentication filter wiring and replaces Spring Security exceptions with domain-specific exceptions. SecurityConfig and JwtAuthenticationFilter are rewired to use dependency injection and UserRepository instead of inline construction with TokenProvider and UserDetailsService. Services now throw NotRoomHostException and NotRoomMemberException instead of AccessDeniedException. Tests are updated to match the new exception types and room-membership checks.

Changes

Authentication Filter Refactoring and Domain Exception Integration

Layer / File(s) Summary
SecurityConfig Bean Wiring
src/main/java/chainsawman/gesture/config/SecurityConfig.java
SecurityConfig removes TokenProvider and CustomUserDetailsService constructor dependencies in favor of injecting a pre-configured JwtAuthenticationFilter bean. The filter chain is rewired to register the injected filter instance while preserving CSRF protection, stateless sessions, and public endpoint authorization.
JwtAuthenticationFilter User Lookup
src/main/java/chainsawman/gesture/security/JwtAuthenticationFilter.java
JwtAuthenticationFilter constructor now injects UserRepository instead of UserDetailsService. Bearer token validation is followed by a user lookup via findByEmailAndIsDeactivatedFalse(), and authentication tokens are constructed with the user entity and empty authorities list.
Service-Level Exception Replacement
src/main/java/chainsawman/gesture/service/RoomService.java, src/main/java/chainsawman/gesture/service/CallService.java, src/main/java/chainsawman/gesture/service/MeetingService.java
RoomService throws NotRoomHostException instead of AccessDeniedException in patchRoom and deleteRoom. CallService throws NotRoomMemberException in joinCall. MeetingService removes the unused AccessDeniedException import as exception handling migrates to domain-specific types.
Exception Messages and HTTP Status Codes
src/main/java/chainsawman/gesture/exceptions/room/NotRoomHostException.java, src/main/java/chainsawman/gesture/exceptions/user/InvalidPasswordException.java, src/main/java/chainsawman/gesture/global/ApiGlobalResponseHandler.java, src/main/java/chainsawman/gesture/service/AuthService.java, src/main/java/chainsawman/gesture/service/UserService.java
NotRoomHostException message describes host-only access. InvalidPasswordException uses UNAUTHORIZED instead of BAD_REQUEST status. ApiGlobalResponseHandler derives validation error messages from the first FieldError. AuthService and UserService imports are corrected to use Spring Transactional and SecurityContextHolder.
CallServiceTest Exception and Repository Updates
src/test/java/chainsawman/gesture/service/CallServiceTest.java
CallServiceTest imports and expects NotRoomMemberException. Call-participant checks are simplified from call-id-based predicates to user-only predicates (existsByUser_IdxAndLeftAtIsNull) across create-new-session, join-existing-session, and already-joined scenarios.
FriendServiceTest Room-Membership Mocking
src/test/java/chainsawman/gesture/service/FriendServiceTest.java
FriendServiceTest adds RoomMemberRepository mock and import. Invite tests stub existsByRoom_IdxAndUser_Idx to return false, enforcing explicit room-membership checks before invite logic executes.
MeetingServiceTest Access Control Refactoring
src/test/java/chainsawman/gesture/service/MeetingServiceTest.java
MeetingServiceTest adds RoomMemberRepository mocking and refactors access control across endMinutes, detail, update, and delete test families. Operations now gate on room-membership via existsByRoom_IdxAndUser_Idx stubs. Access-denied scenarios assert NotRoomMemberException instead of AccessDeniedException. Meeting builders explicitly set the room field.

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant SecurityConfig
  participant JwtAuthenticationFilter
  participant UserRepository
  participant Request
  Client->>SecurityConfig: HTTP request with Authorization header
  SecurityConfig->>JwtAuthenticationFilter: filter chain delegates
  JwtAuthenticationFilter->>JwtAuthenticationFilter: resolve bearer token
  JwtAuthenticationFilter->>JwtAuthenticationFilter: validate token → extract email
  JwtAuthenticationFilter->>UserRepository: findByEmailAndIsDeactivatedFalse(email)
  UserRepository-->>JwtAuthenticationFilter: return User entity
  JwtAuthenticationFilter->>JwtAuthenticationFilter: set UsernamePasswordAuthenticationToken
  JwtAuthenticationFilter->>Request: continue filter chain
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • 3-1-ChoiInSawMan/gesture_SpringBoot_Backend#33: Both PRs touch CallService around joinCall room-membership handling; this PR changes the thrown "not a room member" exception type while the retrieved PR introduces the call-session logic.

  • 3-1-ChoiInSawMan/gesture_SpringBoot_Backend#36: Both PRs involve NotRoomHostException; this PR updates the message and uses it in RoomService access checks while the retrieved PR adds friend-invite enforcement with the same exception.

  • 3-1-ChoiInSawMan/gesture_SpringBoot_Backend#34: This PR removes AccessDeniedException from MeetingService and updates tests to use NotRoomMemberException, overlapping with PR #34's meeting service code that currently depends on AccessDeniedException.

Poem

🐰 A filter hops from constructor calls so deep,
Now UserRepository keeps the secrets to keep,
Domain exceptions bloom where Spring Security's gone—
NotRoomHost and NotRoomMember march on and on. 🎭✨

✨ 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 refactor/jwt-auth-bug-and-http-status-fix

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.

@yoonjeonggg
yoonjeonggg merged commit 92e7aad into main May 22, 2026
1 check was pending
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