Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SIX-256] feat : Refresh Token Rotation 기능 구현 #111

Merged
merged 1 commit into from
Nov 26, 2023
Merged

Conversation

legowww
Copy link
Collaborator

@legowww legowww commented Nov 25, 2023

🖊️ 1. Changes

  • 리프레시 토큰 재발급을 위해 사용되는 AuthController API @GetMapping("/reissue-token") 추가
  • AuthService -> TokenService 네이밍 변경
  • TokenService.rotation() 메서드에서 토큰 재발급 판단

🖼️ 2. Screenshot

❗️ 3. Issues

RTR

  • 정상적인 경우
image
  • 공격자가 토큰을 탈취한 경우
image

REF

😌 4. To Reviewer

사용자에게 전송해주는 리프레시 토큰은 UUID 형태로 사용합니다
전송받은 UUID를 KEY 값으로 레디스에서 불러오는 VALUE 는 deserialize 하여 RefreshToken이라는 클래스로 사용하고 있습니다.

image

RTR 기법에서는 리프레시 토큰은 재발급을 위해 한 번만 사용될 수 있습니다.
chainedToken 은 처음 발급됐을 때는 NONE 값을 가지지만, 해당 리프레시 토큰이 새로운 리프레시 토큰 발급을 위해 사용되는 순간chainedToken 에는 새로 발급된 리프레시 토큰의 UUID가 저장됩니다. 이렇게 체인을 거는것을 token chain 이라고 하는데 키워드로 검색해보시면 좋을 것 같습니다. 현재 구현 수준에서는 하나의 체인만 가지도록 하였습니다.

전체적인 코드 이해를 돕기위해 작동과정만 간단하게 적었습니다.

정상적인 상황

  1. 리프레시 토큰 재발급을 위해 RT1 이 서버에 전송됨
  2. 서버는 RT1 를 KEY 로 레디스에 검색하여 VALUE 를 가져옴
  3. VALUE 의 chainedToken값이 NONE이라면 새로운 AT2, RT2 를 발급하여 클라이언트에게 응답하고 RT1 에 해당하는 VALUE 의 chainedToken 값을 RT2 로 변경하여 레디스에 저장

동일한 리프레시 토큰 재전송

  1. 리프레시 토큰 재발급을 위해 RT1 이 서버에 전송됨
  2. 서버는 RT1 를 KEY 로 레디스에 검색하여 VALUE 를 가져옴
  3. VALUE 의 chainedToken값이 NONE이 아닌 RT2 이기 때문에 해당 리프레시 토큰은 이미 재발급에 사용됐음을 알 수 있음
  4. RT1이 공격자에게 탈취됐다고 판단하여, RT1을 통해 발급받은 RT2 를 레디스에서 제거하여 더이상 사용할 수 없게 만듦
    1. RT2 를 발급받았던 사용자가 정상적인 유저일 경우: 토큰이 취소됐지만, 로그인을 통해 재발급 받으면 문제 없음
    2. RT2 를 발급받았던 사용자가 공격자일 경우: 아이디 비밀번호를 모르기 때문에 더이상의 재발급은 불가능

✅ 5. Plans

  • - 블랙리스트 기법 추가

🙌 6. Checklist

  • - 통합 테스트를 수행해보셨나요?
  • - 혹시 컨벤션에 맞지 않게 작성하지 않았나요?
  • - Change와 Issue, Reviewer를 알아보기 쉽게 작성하였나요?

@legowww legowww self-assigned this Nov 25, 2023
Copy link

Test Results

  56 files    56 suites   8s ⏱️
218 tests 216 ✔️ 2 💤 0
228 runs  226 ✔️ 2 💤 0

Results for commit 74cf3b1.

Copy link

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug B 6 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot E 1 Security Hotspot
Code Smell A 65 Code Smells

62.4% 62.4% Coverage
0.0% 0.0% Duplication

Comment on lines +51 to +54
var refreshTokenValue = tokenService.findRefreshTokenValue(refreshToken);

if (refreshTokenValue.isEmpty()) {
removeCookie(response);
Copy link
Member

Choose a reason for hiding this comment

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

이 부분을 인터셉터로 빼보는 건 어떨까요!?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

오 저 부분때문에 코드 가독성이 떨어지는 것 아닐까 생각했었는데 좋은 아이디어 감사합니다~
리팩토링할 때 수정해보겠습니다!

Copy link
Member

@bombo-dev bombo-dev left a comment

Choose a reason for hiding this comment

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

위에 참고해보시라고 했던 chainToken 은 한 번 살펴보도록 하겠습니다! 👍

Copy link
Collaborator

@heenahan heenahan left a comment

Choose a reason for hiding this comment

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

👍

@legowww legowww merged commit 87df5de into develop Nov 26, 2023
5 checks passed
@legowww legowww deleted the SIX-255 branch November 26, 2023 15:09
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.

3 participants