Skip to content

Conversation

@nayonsoso
Copy link
Collaborator

관련 이슈

작업 내용

  • 로그아웃 시, 엑세스 토큰에 해당하는 리프레시 토큰을 redis 로부터 삭제합니다.
  • 탈퇴 시, 로그아웃합니다.
    • 리프레시 토큰 삭제
    • 액세스 토큰을 블랙리스트에 추가

image

특이 사항

#297 (review) 에서 이야기된 것처럼,
Authentication 으로부터 String accessToken을 추출하는것은 중복 코드가 2곳 뿐이며,
auth 패키지 이외에는 이 로직이 사용되는 곳이 없을 것이기에 ArgumentResolver로 만드는것은 과하다 생각했습니다.
그래서 우선은 private 메서드를 만들어주었습니다.

+) TODO 부분도 빠르게 작업해보겠습니다 🏃‍♀️🏃‍♀️

리뷰 요구사항 (선택)

@nayonsoso nayonsoso self-assigned this May 9, 2025
@coderabbitai
Copy link

coderabbitai bot commented May 9, 2025

"""

Walkthrough

  1. 인증 컨트롤러 리팩토링
     - AuthControllersignOutquit 메서드에서 액세스 토큰 추출 및 검증 로직이 getAccessToken(Authentication)이라는 프라이빗 메서드로 깔끔하게 분리되었습니다.
     - quit 메서드는 이제 Authentication 파라미터를 추가로 받아, 추출한 토큰을 서비스 계층에 전달하도록 바뀌었습니다.

  2. 인증 서비스 로직 개선
     - AuthServicesignOut은 액세스 토큰을 블랙리스트에 추가하는 것뿐 아니라, 해당 토큰과 연결된 리프레시 토큰도 삭제하는 기능이 추가되었습니다.
     - quit 메서드는 사용자 탈퇴 시 로그아웃 처리를 함께 수행하며, 액세스 토큰을 추가 파라미터로 받도록 시그니처가 변경되었습니다.

  3. 토큰 프로바이더 기능 추가
     - AuthTokenProviderdeleteRefreshTokenByAccessToken(AccessToken accessToken) 메서드가 새롭게 추가되어, 액세스 토큰을 기반으로 리프레시 토큰을 Redis에서 삭제할 수 있게 되었습니다.

  4. 인증 서비스 테스트 강화
     - AuthServiceTest에서는 Redis 상태와 토큰 블랙리스트 여부를 검증하는 테스트가 보강되었습니다.
     - signOutquit 테스트 모두에서 리프레시 토큰 삭제와 액세스 토큰 블랙리스트 등록을 확인하는 검증이 포함되어 안정성을 높였습니다.

  5. 토큰 프로바이더 테스트 추가
     - AuthTokenProviderTest에 액세스 토큰으로 대응되는 리프레시 토큰이 제대로 삭제되는지 확인하는 테스트 메서드가 추가되었습니다.
     - 이 테스트는 Redis에서 리프레시 토큰 키가 정상적으로 삭제되는지를 꼼꼼히 검증합니다.

Suggested reviewers

  • wibaek
    """

Tip

⚡️ Faster reviews with caching
  • CodeRabbit now supports caching for code and dependencies, helping speed up reviews. This means quicker feedback, reduced wait times, and a smoother review experience overall. Cached data is encrypted and stored securely. This feature will be automatically enabled for all accounts on May 16th. To opt out, configure Review - Disable Cache at either the organization or repository level. If you prefer to disable all data retention across your organization, simply turn off the Data Retention setting under your Organization Settings.

Enjoy the performance boost—your workflow just got faster.


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9af3c3f and 8deddff.

📒 Files selected for processing (1)
  • src/main/java/com/example/solidconnection/auth/controller/AuthController.java (2 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • src/main/java/com/example/solidconnection/auth/controller/AuthController.java
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Generate unit testing code for this file.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai generate unit testing code for this file.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and generate unit testing code.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

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: 0

🧹 Nitpick comments (2)
src/main/java/com/example/solidconnection/auth/controller/AuthController.java (2)

97-103: 좋은 리팩토링이지만 공백 토큰에 대한 검증이 제거되었어요.

  1. 리팩토링의 장점:

    • 중복 코드를 getAccessToken 메서드로 추출하여 코드 가독성 향상
    • 토큰 추출 로직을 한 곳에서 관리하여 유지보수성 개선
  2. 주의 사항:

    • 이전 코드에서는 토큰이 null인지와 공백인지 모두 확인했을 가능성이 있습니다
    • 새로운 getAccessToken 메서드는 null 체크만 수행하고 있어요
    • 공백 토큰도 유효하지 않은 입력으로 처리하는 것이 좋을 수 있습니다
private String getAccessToken(Authentication authentication) {
    String accessToken = (String) authentication.getCredentials();
    if (accessToken == null) {
        throw new CustomException(ErrorCode.AUTHENTICATION_FAILED, "엑세스 토큰이 없습니다.");
    }
+   if (accessToken.isBlank()) {
+       throw new CustomException(ErrorCode.AUTHENTICATION_FAILED, "엑세스 토큰이 비어있습니다.");
+   }
    return accessToken;
}

122-129: 토큰 추출 및 검증 로직을 분리한 것은 매우 좋은 리팩토링입니다.

  1. 잘 구현된 점:

    • 중복 코드 제거로 DRY 원칙 준수
    • 명확한 예외 메시지로 디버깅 용이성 향상
    • 프라이빗 메서드로 구현하여 캡슐화 적용
  2. 추가 개선 가능성:

    • 앞서 언급한 공백 토큰 검증을 추가하면 더 견고해질 것
    • 에러 메시지의 오타 수정: "엑세스" → "액세스"
private String getAccessToken(Authentication authentication) {
    String accessToken = (String) authentication.getCredentials();
    if (accessToken == null) {
-       throw new CustomException(ErrorCode.AUTHENTICATION_FAILED, "엑세스 토큰이 없습니다.");
+       throw new CustomException(ErrorCode.AUTHENTICATION_FAILED, "액세스 토큰이 없습니다.");
    }
    return accessToken;
}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 9713f51 and d837cd9.

📒 Files selected for processing (5)
  • src/main/java/com/example/solidconnection/auth/controller/AuthController.java (2 hunks)
  • src/main/java/com/example/solidconnection/auth/service/AuthService.java (1 hunks)
  • src/main/java/com/example/solidconnection/auth/service/AuthTokenProvider.java (1 hunks)
  • src/test/java/com/example/solidconnection/auth/service/AuthServiceTest.java (3 hunks)
  • src/test/java/com/example/solidconnection/auth/service/AuthTokenProviderTest.java (1 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
  • GitHub Check: build
🔇 Additional comments (14)
src/main/java/com/example/solidconnection/auth/service/AuthTokenProvider.java (1)

52-56: 리프레시 토큰 삭제 기능이 잘 구현되었습니다.

새로운 deleteRefreshTokenByAccessToken 메서드가 깔끔하게 구현되었습니다. 이 구현은:

  1. 액세스 토큰에서 subject 값을 추출하고
  2. 해당 subject로 리프레시 토큰 키를 생성한 후
  3. Redis에서 리프레시 토큰을 삭제합니다

구현이 간결하고 목적에 부합합니다.

src/test/java/com/example/solidconnection/auth/service/AuthTokenProviderTest.java (1)

73-85: 테스트 케이스가 명확하게 작성되었습니다.

새로 추가된 액세서_토큰에_해당하는_리프레시_토큰을_삭제한다 테스트는 다음과 같이 잘 구성되어 있습니다:

  1. 주어진 subject에 대한 리프레시 토큰 생성 및 저장
  2. 동일한 subject에 대한 액세스 토큰 생성
  3. 액세스 토큰을 사용하여 deleteRefreshTokenByAccessToken 메서드 호출
  4. Redis에서 리프레시 토큰이 삭제되었는지 검증

given-when-then 구조가 명확하고, 검증 로직이 적절합니다.

src/main/java/com/example/solidconnection/auth/service/AuthService.java (5)

22-24: 문서 업데이트가 적절히 이루어졌습니다.

로그아웃 메서드의 javadoc이 새로운 기능(리프레시 토큰 삭제)을 반영하도록 적절히 업데이트되었습니다.


28-28: 리프레시 토큰 삭제 로직이 적절히 추가되었습니다.

로그아웃 시 리프레시 토큰을 삭제하는 로직이 성공적으로 구현되었습니다. 이는 보안 측면에서 중요한 개선사항입니다.


33-37: 문서 업데이트가 적절히 이루어졌습니다.

탈퇴 메서드의 javadoc이 새로운 기능(로그아웃 처리)을 반영하도록 적절히 업데이트되었습니다.


39-39: TODO 코멘트가 명확하게 작성되었습니다.

TODO 코멘트는 향후 개선 방향을 명확하게 제시하고 있습니다. 이슈 번호(#299)를 포함하여 추적이 용이하도록 작성되었습니다.

미래에 SiteUser 파라미터를 제거하고 token만 받도록 수정하는 것은 결합도를 낮추는 좋은 방향입니다.


42-42: 로그아웃 로직이 적절히 통합되었습니다.

탈퇴 과정에서 로그아웃 처리가 적절히 추가되었습니다. 이렇게 함으로써 사용자 탈퇴 시 인증 토큰이 깔끔하게 정리됩니다.

src/test/java/com/example/solidconnection/auth/service/AuthServiceTest.java (6)

38-40: RedisTemplate 주입이 적절히 추가되었습니다.

RedisTemplate을 주입받아 Redis 상태 변화를 검증할 수 있도록 테스트가 개선되었습니다.


44-46: 테스트 준비 단계가 적절히 개선되었습니다.

테스트에 필요한 Subject 객체와 AccessToken 객체를 생성하는 코드가 명확하게 추가되었습니다.


51-55: 검증 로직이 적절히 강화되었습니다.

로그아웃 후 다음 사항을 검증하도록 테스트가 개선되었습니다:

  1. Redis에서 리프레시 토큰이 삭제되었는지 확인
  2. 액세스 토큰이 블랙리스트에 추가되었는지 확인

assertAll을 사용하여 여러 검증을 한 번에 실행하는 것이 좋은 접근법입니다.


62-64: 테스트 준비 단계가 적절히 개선되었습니다.

사용자 객체에서 Subject를 추출하고 AccessToken을 생성하는 코드가 명확하게 추가되었습니다.


66-66: 서비스 호출이 새로운 메서드 시그니처에 맞게 업데이트되었습니다.

quit 메서드 호출이 새로운 시그니처(토큰 파라미터 추가)에 맞게 올바르게 업데이트되었습니다.


70-75: 검증 로직이 적절히 강화되었습니다.

탈퇴 후 다음 사항을 검증하도록 테스트가 개선되었습니다:

  1. 사용자의 탈퇴일이 내일로 설정되었는지 확인
  2. Redis에서 리프레시 토큰이 삭제되었는지 확인
  3. 액세스 토큰이 블랙리스트에 추가되었는지 확인

assertAll을 사용하여 여러 검증을 한 번에 실행하는 것이 좋은 접근법입니다.

src/main/java/com/example/solidconnection/auth/controller/AuthController.java (1)

105-113: 매개변수 추가와 토큰 전달 로직 개선이 잘 이루어졌습니다.

  1. 개선된 점:

    • Authentication 매개변수가 추가되어 토큰 추출 가능
    • 추출된 액세스 토큰이 서비스 계층으로 전달되어 요구사항 구현
    • 코드가 간결해지고 책임이 명확하게 분리됨
  2. 기대 효과:

    • PR 목표대로 회원 탈퇴 시 리프레시 토큰 삭제 기능 지원
    • 인증 관련 작업이 일관된 방식으로 처리됨

@nayonsoso nayonsoso force-pushed the refactor/298-invalidate-refresh-token branch from d837cd9 to 9af3c3f Compare May 9, 2025 18:15
- Authentication 자체가 null 인 경우도 예외처리
@nayonsoso nayonsoso force-pushed the refactor/298-invalidate-refresh-token branch from 9af3c3f to 8deddff Compare May 9, 2025 18:47
Copy link
Member

@wibaek wibaek left a comment

Choose a reason for hiding this comment

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

오래된 #99 issue가 solve 됐네요! lgtm!

Copy link
Contributor

@Gyuhyeok99 Gyuhyeok99 left a comment

Choose a reason for hiding this comment

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

확인했습니다! 함수명 가독성이 참 좋은 거 같네요 ㅎㅎ
보다가 갑자기 의문이 든 건 로그아웃 api HTTP 메서드가 PATCH인가?라는 생각이 들었습니다!
부분 수정의 느낌보다는 상태 변경이라고 해야할까요..? 그래서 POST가 더 맞는 거 같다는 생각이 드는데 어떻게 생각하시나요?

@nayonsoso nayonsoso merged commit 3b16bda into solid-connection:develop May 10, 2025
2 checks passed
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: 로그아웃 시 리프레시 토큰을 삭제한다. 회원탈퇴시 토큰이 소멸되지 않는 문제

3 participants