FIX : 카카오 가입 완료 복구와 역할 권한 상승 차단, UserService 테스트 - #104
Merged
Merged
Conversation
UserService 테스트를 쓰다가 카카오 가입 완료 경로에서 결함 두 개를 찾았다.
하나만 고치면 더 나빠지는 구조라 함께 고친다.
1) 카카오 신규 가입이 전부 막혀 있었다.
카카오 로그인은 가입 미완료 사용자에게도 토큰을 주고, 프런트는 그 토큰으로
/auth/kakao/complete-registration 을 부른다. 그런데 JWT 필터가
path.startsWith("/auth/kakao") 로 통째로 건너뛰어 토큰이 해석되지 않았고,
컨트롤러가 현재 사용자를 찾다가 401 을 냈다. 통합 테스트로 재현했다
(유효한 토큰으로 호출해도 expected 200 but was 401).
필터 예외를 /auth/kakao/login, /auth/kakao/login-url 로 좁히고,
SecurityConfig 에서 가입 완료를 authenticated() 로 바꿨다.
2) 역할을 클라이언트가 정했다.
요청 본문의 role 을 UserRole.valueOf 로 그대로 저장했고, 오류 메시지가
"가능한 역할: PARENT, CAREGIVER, ADMIN, GUEST" 라고 알려주기까지 했다.
{"role":"ADMIN"} 이면 그 자리에서 관리자다. 이메일 가입의 #82 와 같다.
지금까지 드러나지 않은 건 1번이 흐름을 막고 있었기 때문이다. 1번만 고치면 그대로 열린다.
스스로 고를 수 있는 역할을 허용 목록(PARENT, CAREGIVER)으로 제한했다. 금지 목록이
아니라 허용 목록이라, 나중에 특권 역할이 추가돼도 기본으로 막힌다.
프런트 가입 화면은 PARENT 로 고정해 보내므로 깨지지 않는다.
3) Boolean 언박싱 3곳을 null 안전하게 했다.
registrationCompleted / isActive 가 Boolean 인데 !x.get...(), x.get...() && 로 언박싱했다.
null 이면 카카오 로그인(AuthServiceImpl), 가입 완료, 계정 복구가 NPE 로 500 이었다.
UserService 테스트 (#93)
라인 커버리지 0.7% → 95.8%. 0.7% 였던 동안 이 클래스에서 P0 가 세 번 나왔다
(#82 가입 role, #83 역할 변경 노출, 그리고 이번 카카오 role).
build.gradle 의 CLASS 60% 규칙에 UserService 를 넣고, 전체 ratchet 을 0.30 → 0.35 로 올렸다.
@PreAuthorize 는 스프링 프록시가 적용하므로 단위 테스트 범위 밖이다. 그 계약은
접근제어 통합 테스트가 맡는다.
460 tests, 0 failures. 전체 라인 커버리지 34.9% → 37.8%.
1 of 5 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
🏫 관련 이슈
Closes #93
Closes #103
🏫 PR 타입
🏫 반영 브랜치
test/user-service-coverage->main🏫 변경 사항
#93(
UserService커버리지 0.7%)을 하러 들어갔다가, 테스트를 쓰면서 카카오 가입 완료 경로에서 P0 를 찾았다 (#103).1. 카카오 신규 가입이 전부 막혀 있었다 ⭐
통합 테스트로 재현했다. 유효한 토큰을 들고도
expected: 200 but was: 401.카카오로 처음 들어온 사람은 누구도 가입을 끝낼 수 없었다.
→ 필터 예외를
/auth/kakao/login,/auth/kakao/login-url로 좁히고, 가입 완료를authenticated()로.2. 역할을 클라이언트가 정했다 — 누구나 관리자 ⭐
이메일 가입의 #82 와 같은 결함이다.
이 두 결함은 하나만 고치면 더 나빠진다. 지금까지 2번이 드러나지 않은 건 1번이 흐름을 막고
있었기 때문이다. 1번만 고쳤다면 카카오 로그인 한 번으로 관리자가 되는 경로가 열렸을 것이다.
→ 스스로 고를 수 있는 역할을 허용 목록(PARENT, CAREGIVER)으로 제한.
금지 목록이 아니라서 나중에 특권 역할이 추가돼도 기본으로 막힌다.
프런트 가입 화면은
role: 'PARENT'고정이라 깨지지 않는다.3. Boolean 언박싱 NPE 3곳
registrationCompleted/isActive가Boolean인데!x.getRegistrationCompleted(),x.getIsActive() &&로 언박싱했다. null 이면 카카오 로그인(AuthServiceImpl)·가입 완료·계정 복구가 500.4. UserService 테스트 (#93)
UserService라인 커버리지UserService추가0.7% 였던 동안 이 클래스에서 P0 가 세 번 나왔다 — #82 가입 role, #83 역할 변경 노출, 그리고 이번 카카오 role.
@PreAuthorize는 스프링 프록시가 적용해서 단위 테스트 범위 밖이다. 그 계약은AccessControlContractTest/EndpointAuthorizationCoverageTest가 맡는다.🏫 테스트 결과
KakaoRegistrationCompletionTest(6, 통합)UserServiceTest(43)EndpointAuthorizationCoverageTest의 공개 목록에서 가입 완료를 뺐다. 그 자리에 "예전에 공개로 적혀 있었고그래서 흐름 전체가 401 이었다" 는 주석을 남겼다 — 누가 다시 넣지 않도록.
🏫 To Reviewer
(
hasRole전수 확인) 안전하지만, 보육사에 별도 권한을 붙일 계획이 있다면 그 전에 허용 목록에서 빼야 한다.AuthServiceImpl커버리지가 1% 다. 카카오 로그인 본체인데, 이번에 언박싱 한 줄만 고치고테스트는 붙이지 않았다. 계정 연결(같은 이메일의 기존 계정에 카카오를 붙이는 로직)이 들어 있어
다음으로 봐야 할 곳이다.
getKakaoUserInfo가 카카오 액세스 토큰 앞 20자를 INFO 로그에 남긴다. 이번 범위에서는 손대지 않았다.