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

[#29] refresh token 재발급 API 추가 #30

Merged
merged 2 commits into from
Sep 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
package com.dnd.dndtravel.auth.controller;

import com.dnd.dndtravel.auth.controller.request.ReIssueTokenRequest;
import com.dnd.dndtravel.auth.service.dto.response.AppleIdTokenPayload;
import com.dnd.dndtravel.auth.service.AppleOAuthService;
import com.dnd.dndtravel.auth.service.JwtTokenService;
import com.dnd.dndtravel.auth.controller.request.AppleLoginRequest;
import com.dnd.dndtravel.auth.service.dto.response.TokenResponse;
import com.dnd.dndtravel.auth.service.dto.response.ReissueTokenResponse;
import com.dnd.dndtravel.member.domain.Member;
import com.dnd.dndtravel.member.service.MemberService;

Expand Down Expand Up @@ -41,4 +43,9 @@ public ResponseEntity<TokenResponse> appleOAuthLogin(@RequestBody AppleLoginRequ

return ResponseEntity.ok(tokenResponse);
}

@PostMapping("/reissue/token")
public ReissueTokenResponse reissueToken(@RequestBody ReIssueTokenRequest reissueTokenRequest) {
return jwtTokenService.reIssue(reissueTokenRequest.refreshToken());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.dnd.dndtravel.auth.controller.request;

public record ReIssueTokenRequest(
String refreshToken
) {
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
package com.dnd.dndtravel.auth.repository;


import java.util.Optional;

import com.dnd.dndtravel.auth.domain.RefreshToken;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

@Repository
public interface RefreshTokenRepository extends JpaRepository<RefreshToken, Long> {
RefreshToken findByMemberId(Long memberId);

Optional<RefreshToken> findByRefreshToken(String refreshToken);
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,8 @@ public String accessToken(Long memberId) {
.compact();
}

public String refreshToken(Long memberId) {
public String refreshToken() {
return Jwts.builder()
.claim(CLAIM_CONTENT, memberId)
.issuedAt(new Date(System.currentTimeMillis()))
.expiration(new Date(System.currentTimeMillis() + this.refreshTokenExpiredTime))
.signWith(secretKey)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import com.dnd.dndtravel.auth.domain.RefreshToken;
import com.dnd.dndtravel.auth.repository.RefreshTokenRepository;
import com.dnd.dndtravel.auth.service.dto.response.TokenResponse;
import com.dnd.dndtravel.auth.service.dto.response.ReissueTokenResponse;

import lombok.RequiredArgsConstructor;

Expand All @@ -21,7 +22,7 @@ public TokenResponse generateTokens(Long memberId) {
RefreshToken refreshToken = refreshTokenRepository.findByMemberId(memberId);

if (refreshToken == null) {
String newRefreshToken = jwtProvider.refreshToken(memberId);
String newRefreshToken = jwtProvider.refreshToken();
refreshTokenRepository.save(RefreshToken.of(memberId, newRefreshToken)); // refreshToken은 DB에 저장
return new TokenResponse(jwtProvider.accessToken(memberId), newRefreshToken);
} else if (refreshToken.isExpire()) {
Expand All @@ -30,4 +31,16 @@ public TokenResponse generateTokens(Long memberId) {

return new TokenResponse(jwtProvider.accessToken(memberId), null);
}

@Transactional
public ReissueTokenResponse reIssue(String token) {
//validation
RefreshToken refreshToken = refreshTokenRepository.findByRefreshToken(token).orElseThrow(() -> new RuntimeException("유효하지 않은 토큰"));

//RTR
refreshTokenRepository.delete(refreshToken);
String newRefreshToken = jwtProvider.refreshToken();
refreshTokenRepository.save(RefreshToken.of(refreshToken.getMemberId(), newRefreshToken));
return new ReissueTokenResponse(jwtProvider.accessToken(refreshToken.getMemberId()), newRefreshToken);
Comment on lines +40 to +44
Copy link
Member

Choose a reason for hiding this comment

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

Refresh Token Rotation전략이 해당 부분 리프레시 토큰 요청 시 기존 토큰을 폐기하고, 새 토큰을 클라이언트에 발급하는 것이군용
뭔가 간단한 논리인데 토큰 탈취를 막고 보안성을 높일 수 있다는 것이 신기함니당

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package com.dnd.dndtravel.auth.service.dto.response;

public record ReissueTokenResponse(
String accessToken,
String refreshToken
) {
}
Loading